From 94293a42db08bf7c9199f93e4097321145a1ef41 Mon Sep 17 00:00:00 2001 From: Pablo Gamito Date: Sat, 19 Dec 2020 19:36:40 +0100 Subject: [PATCH 001/219] Register mock tokens in json database Allows all steps of the aave:dev task to run successfully --- helpers/contracts-deployments.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 322e4f18..739ade34 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -387,6 +387,7 @@ export const deployAllMockTokens = async (verify?: boolean) => { [tokenSymbol, tokenSymbol, configData ? configData.reserveDecimals : decimals], verify ); + await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); } return tokens; }; From 15076ea7c03b68f0e011ecdbb51cf3f95e7a80ce Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 21 Dec 2020 16:14:07 -0500 Subject: [PATCH 002/219] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ae2e7b69..8e4b0049 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +### Uniswap V2 Market Aave Fork ``` .///. .///. //. .// `/////////////- `++:++` .++:++` :++` `++: `++:......---.` From 9e001ec0b6c522ed888b3328ac473505e73f0f5e Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Tue, 22 Dec 2020 18:48:02 -0500 Subject: [PATCH 003/219] Initial testing --- helpers/configuration.ts | 3 + helpers/contracts-deployments.ts | 1 + helpers/contracts-getters.ts | 2 + helpers/oracles-helpers.ts | 6 + helpers/types.ts | 19 + markets/aave/commons.ts | 2 + markets/uniswap/commons.ts | 334 ++ markets/uniswap/index.ts | 88 + markets/uniswap/reservesConfigs.ts | 122 + package-lock.json | 4802 ++++++----------- tasks/dev/3_uniswap_address_provider.ts | 28 + .../{3_lending_pool.ts => 4_lending_pool.ts} | 0 tasks/dev/{4_oracles.ts => 5_oracles.ts} | 58 +- .../dev/{5_initialize.ts => 6_initialize.ts} | 0 ...ovider.ts => 7_wallet_balance_provider.ts} | 0 tasks/migrations/aave.dev.ts | 14 +- 16 files changed, 2234 insertions(+), 3245 deletions(-) create mode 100644 markets/uniswap/commons.ts create mode 100644 markets/uniswap/index.ts create mode 100644 markets/uniswap/reservesConfigs.ts create mode 100644 tasks/dev/3_uniswap_address_provider.ts rename tasks/dev/{3_lending_pool.ts => 4_lending_pool.ts} (100%) rename tasks/dev/{4_oracles.ts => 5_oracles.ts} (72%) rename tasks/dev/{5_initialize.ts => 6_initialize.ts} (100%) rename tasks/dev/{6_wallet_balance_provider.ts => 7_wallet_balance_provider.ts} (100%) diff --git a/helpers/configuration.ts b/helpers/configuration.ts index a06ce3b3..925f9365 100644 --- a/helpers/configuration.ts +++ b/helpers/configuration.ts @@ -8,6 +8,7 @@ import { } from './types'; import { getParamPerPool } from './contracts-helpers'; import AaveConfig from '../markets/aave'; +import UniswapConfig from '../markets/uniswap'; import { CommonsConfig } from '../markets/aave/commons'; import { DRE, filterMapBy } from './misc-utils'; import { tEthereumAddress } from './types'; @@ -26,6 +27,8 @@ export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => { return AaveConfig; case ConfigNames.Commons: return CommonsConfig; + case ConfigNames.Uniswap: + return UniswapConfig; default: throw new Error(`Unsupported pool configuration: ${Object.values(ConfigNames)}`); } diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 322e4f18..0cb00122 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -387,6 +387,7 @@ export const deployAllMockTokens = async (verify?: boolean) => { [tokenSymbol, tokenSymbol, configData ? configData.reserveDecimals : decimals], verify ); + console.log("deployAllMockTokens: deployed", tokenSymbol); } return tokens; }; diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index 65834cc6..22c1784b 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -153,7 +153,9 @@ export const getAllMockedTokens = async () => { const tokens: MockTokenMap = await Object.keys(TokenContractId).reduce>( async (acc, tokenSymbol) => { const accumulator = await acc; + console.log("getAllMockedTokens: got accumulator"); const address = db.get(`${tokenSymbol.toUpperCase()}.${DRE.network.name}`).value().address; + console.log("getAllMockedTokens: Initialized address for %s, address: %s", tokenSymbol, address); accumulator[tokenSymbol] = await getMintableERC20(address); return Promise.resolve(acc); }, diff --git a/helpers/oracles-helpers.ts b/helpers/oracles-helpers.ts index 45cec5e2..242161e4 100644 --- a/helpers/oracles-helpers.ts +++ b/helpers/oracles-helpers.ts @@ -38,6 +38,12 @@ export const setInitialMarketRatesInRatesOracleByHelper = async ( borrowRates.push(borrowRate); symbols.push(assetSymbol); } + + console.log("---setInitialMarketRatesInRatesOracleByHelper---"); + console.log(assetAddresses); + console.log(symbols); + console.log(borrowRates); + // Set borrow rates per chunks const ratesChunks = 20; const chunkedTokens = chunk(assetAddresses, ratesChunks); diff --git a/helpers/types.ts b/helpers/types.ts index 35211dd1..30c628e6 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -200,6 +200,8 @@ export interface iAssetBase { USD: T; REN: T; ENJ: T; + WETHDAI: T; + WETHWBTC: T; } export type iAssetsWithoutETH = Omit, 'ETH'>; @@ -230,6 +232,17 @@ export type iAavePoolAssets = Pick< | 'ENJ' >; +export type iUniswapPoolAssets = Pick< + iAssetsWithoutUSD, + | 'DAI' + | 'USDC' + | 'USDT' + | 'WBTC' + | 'WETH' + | 'WETHDAI' + | 'WETHWBTC' +>; + export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; export type iAavePoolTokens = Omit, 'ETH'>; @@ -258,6 +271,8 @@ export enum TokenContractId { YFI = 'YFI', UNI = 'UNI', ENJ = 'ENJ', + WETHDAI = 'WETHDAI', + WETHWBTC = 'WETHWBTC', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { @@ -372,6 +387,10 @@ export interface ICommonConfiguration { export interface IAaveConfiguration extends ICommonConfiguration { ReservesConfig: iAavePoolAssets; } + +export interface IUniswapConfiguration extends ICommonConfiguration { + ReservesConfig: iUniswapPoolAssets; +} export interface ITokenAddress { [token: string]: tEthereumAddress; } diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index f2fdb6f3..fecd714f 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -23,6 +23,8 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), + WETHDAI: oneEther.multipliedBy('22.407436').toFixed(), + WETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; // ---------------- diff --git a/markets/uniswap/commons.ts b/markets/uniswap/commons.ts new file mode 100644 index 00000000..939b32ee --- /dev/null +++ b/markets/uniswap/commons.ts @@ -0,0 +1,334 @@ +import BigNumber from 'bignumber.js'; +import { oneEther, oneRay, RAY, ZERO_ADDRESS } from '../../helpers/constants'; +import { ICommonConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; + +const MOCK_CHAINLINK_AGGREGATORS_PRICES = { + AAVE: oneEther.multipliedBy('0.003620948469').toFixed(), + BAT: oneEther.multipliedBy('0.00137893825230').toFixed(), + BUSD: oneEther.multipliedBy('0.00736484').toFixed(), + DAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + ENJ: oneEther.multipliedBy('0.00029560').toFixed(), + KNC: oneEther.multipliedBy('0.001072').toFixed(), + LINK: oneEther.multipliedBy('0.009955').toFixed(), + MANA: oneEther.multipliedBy('0.000158').toFixed(), + MKR: oneEther.multipliedBy('2.508581').toFixed(), + REN: oneEther.multipliedBy('0.00065133').toFixed(), + SNX: oneEther.multipliedBy('0.00442616').toFixed(), + SUSD: oneEther.multipliedBy('0.00364714136416').toFixed(), + TUSD: oneEther.multipliedBy('0.00364714136416').toFixed(), + UNI: oneEther.multipliedBy('0.00536479').toFixed(), + USDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + USDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + WETH: oneEther.toFixed(), + WBTC: oneEther.multipliedBy('47.332685').toFixed(), + YFI: oneEther.multipliedBy('22.407436').toFixed(), + ZRX: oneEther.multipliedBy('0.001151').toFixed(), + WETHDAI: oneEther.multipliedBy('22.407436').toFixed(), + WETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), + USD: '5848466240000000', +}; +// ---------------- +// PROTOCOL GLOBAL PARAMS +// ---------------- + +export const CommonsConfig: ICommonConfiguration = { + MarketId: 'Commons', + ProviderId: 0, + 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(), + }, + DAI: { + borrowRate: oneRay.multipliedBy(0.039).toFixed(), + }, + TUSD: { + borrowRate: oneRay.multipliedBy(0.035).toFixed(), + }, + USDC: { + borrowRate: oneRay.multipliedBy(0.039).toFixed(), + }, + SUSD: { + borrowRate: oneRay.multipliedBy(0.035).toFixed(), + }, + USDT: { + borrowRate: oneRay.multipliedBy(0.035).toFixed(), + }, + BAT: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + AAVE: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + LINK: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + KNC: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + MKR: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + MANA: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + WBTC: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + ZRX: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + SNX: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + YFI: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + REN: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + UNI: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + BUSD: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + WETHDAI: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + WETHWBTC: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + }, + // ---------------- + // COMMON PROTOCOL ADDRESSES ACROSS POOLS + // ---------------- + + // If PoolAdmin/emergencyAdmin is set, will take priority over PoolAdminIndex/emergencyAdminIndex + PoolAdmin: { + [eEthereumNetwork.coverage]: undefined, + [eEthereumNetwork.buidlerevm]: undefined, + [eEthereumNetwork.coverage]: undefined, + [eEthereumNetwork.hardhat]: undefined, + [eEthereumNetwork.kovan]: undefined, + [eEthereumNetwork.ropsten]: undefined, + [eEthereumNetwork.main]: undefined, + [eEthereumNetwork.tenderlyMain]: undefined, + }, + PoolAdminIndex: 0, + EmergencyAdmin: { + [eEthereumNetwork.hardhat]: undefined, + [eEthereumNetwork.coverage]: undefined, + [eEthereumNetwork.buidlerevm]: undefined, + [eEthereumNetwork.kovan]: undefined, + [eEthereumNetwork.ropsten]: undefined, + [eEthereumNetwork.main]: undefined, + [eEthereumNetwork.tenderlyMain]: undefined, + }, + EmergencyAdminIndex: 1, + ProviderRegistry: { + [eEthereumNetwork.kovan]: '0x1E40B561EC587036f9789aF83236f057D1ed2A90', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', + }, + ProviderRegistryOwner: { + [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', + }, + LendingRateOracle: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', + [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', + [eEthereumNetwork.main]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', + [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', + }, + TokenDistributor: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.hardhat]: '', + [EthereumNetwork.kovan]: '0x971efe90088f21dc6a36f610ffed77fc19710708', + [EthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c', + [EthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', + [EthereumNetwork.tenderlyMain]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', + }, + AaveOracle: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [EthereumNetwork.kovan]: '0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', + [EthereumNetwork.ropsten]: ZERO_ADDRESS, + [EthereumNetwork.main]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', + [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', + }, + FallbackOracle: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [EthereumNetwork.kovan]: '0x50913E8E1c650E790F8a1E741FF9B1B1bB251dfe', + [EthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d', + [EthereumNetwork.main]: ZERO_ADDRESS, + [EthereumNetwork.tenderlyMain]: ZERO_ADDRESS, + }, + ChainlinkAggregator: { + [eEthereumNetwork.coverage]: {}, + [eEthereumNetwork.hardhat]: {}, + [eEthereumNetwork.buidlerevm]: {}, + [EthereumNetwork.kovan]: { + AAVE: '0xd04647B7CB523bb9f26730E9B6dE1174db7591Ad', + BAT: '0x0e4fcEC26c9f85c3D714370c98f43C4E02Fc35Ae', + BUSD: '0xbF7A18ea5DE0501f7559144e702b29c55b055CcB', + DAI: '0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', + ENJ: '0xfaDbe2ee798889F02d1d39eDaD98Eff4c7fe95D4', + KNC: '0xb8E8130d244CFd13a75D6B9Aee029B1C33c808A7', + LINK: '0x3Af8C569ab77af5230596Acf0E8c2F9351d24C38', + MANA: '0x1b93D8E109cfeDcBb3Cc74eD761DE286d5771511', + MKR: '0x0B156192e04bAD92B6C1C13cf8739d14D78D5701', + REN: '0xF1939BECE7708382b5fb5e559f630CB8B39a10ee', + SNX: '0xF9A76ae7a1075Fe7d646b06fF05Bd48b9FA5582e', + SUSD: '0xb343e7a1aF578FA35632435243D814e7497622f7', + TUSD: '0x7aeCF1c19661d12E962b69eBC8f6b2E63a55C660', + UNI: '0x17756515f112429471F86f98D5052aCB6C47f6ee', + USDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', + USDT: '0x0bF499444525a23E7Bb61997539725cA2e928138', + WBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', + YFI: '0xC5d1B1DEb2992738C0273408ac43e1e906086B6C', + ZRX: '0xBc3f28Ccc21E9b5856E81E6372aFf57307E2E883', + USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', + }, + [EthereumNetwork.ropsten]: { + AAVE: ZERO_ADDRESS, + BAT: '0xafd8186c962daf599f171b8600f3e19af7b52c92', + BUSD: '0x0A32D96Ff131cd5c3E0E5AAB645BF009Eda61564', + DAI: '0x64b8e49baded7bfb2fd5a9235b2440c0ee02971b', + ENJ: ZERO_ADDRESS, + KNC: '0x19d97ceb36624a31d827032d8216dd2eb15e9845', + LINK: '0xb8c99b98913bE2ca4899CdcaF33a3e519C20EeEc', + MANA: '0xDab909dedB72573c626481fC98CEE1152b81DEC2', + MKR: '0x811B1f727F8F4aE899774B568d2e72916D91F392', + REN: ZERO_ADDRESS, + SNX: '0xA95674a8Ed9aa9D2E445eb0024a9aa05ab44f6bf', + SUSD: '0xe054b4aee7ac7645642dd52f1c892ff0128c98f0', + TUSD: '0x523ac85618df56e940534443125ef16daf785620', + UNI: ZERO_ADDRESS, + USDC: '0xe1480303dde539e2c241bdc527649f37c9cbef7d', + USDT: '0xc08fe0c4d97ccda6b40649c6da621761b628c288', + WBTC: '0x5b8B87A0abA4be247e660B0e0143bB30Cdf566AF', + YFI: ZERO_ADDRESS, + ZRX: '0x1d0052e4ae5b4ae4563cbac50edc3627ca0460d7', + USD: '0x8468b2bDCE073A157E560AA4D9CcF6dB1DB98507', + }, + [EthereumNetwork.main]: { + AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', + BAT: '0x0d16d4528239e9ee52fa531af613AcdB23D88c94', + BUSD: '0x614715d2Af89E6EC99A233818275142cE88d1Cfd', + DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', + ENJ: '0x24D9aB51950F3d62E9144fdC2f3135DAA6Ce8D1B', + KNC: '0x656c0544eF4C98A6a98491833A89204Abb045d6b', + LINK: '0xDC530D9457755926550b59e8ECcdaE7624181557', + MANA: '0x82A44D92D6c329826dc557c5E1Be6ebeC5D5FeB9', + MKR: '0x24551a8Fb2A7211A25a17B1481f043A8a8adC7f2', + REN: '0x3147D7203354Dc06D9fd350c7a2437bcA92387a4', + SNX: '0x79291A9d692Df95334B1a0B3B4AE6bC606782f8c', + SUSD: '0x8e0b7e6062272B5eF4524250bFFF8e5Bd3497757', + TUSD: '0x3886BA987236181D98F2401c507Fb8BeA7871dF2', + UNI: '0xD6aA3D25116d8dA79Ea0246c4826EB951872e02e', + USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', + USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', + WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', + YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4', + ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', + USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + }, + [EthereumNetwork.tenderlyMain]: { + AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', + BAT: '0x0d16d4528239e9ee52fa531af613AcdB23D88c94', + BUSD: '0x614715d2Af89E6EC99A233818275142cE88d1Cfd', + DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', + ENJ: '0x24D9aB51950F3d62E9144fdC2f3135DAA6Ce8D1B', + KNC: '0x656c0544eF4C98A6a98491833A89204Abb045d6b', + LINK: '0xDC530D9457755926550b59e8ECcdaE7624181557', + MANA: '0x82A44D92D6c329826dc557c5E1Be6ebeC5D5FeB9', + MKR: '0x24551a8Fb2A7211A25a17B1481f043A8a8adC7f2', + REN: '0x3147D7203354Dc06D9fd350c7a2437bcA92387a4', + SNX: '0x79291A9d692Df95334B1a0B3B4AE6bC606782f8c', + SUSD: '0x8e0b7e6062272B5eF4524250bFFF8e5Bd3497757', + TUSD: '0x3886BA987236181D98F2401c507Fb8BeA7871dF2', + UNI: '0xD6aA3D25116d8dA79Ea0246c4826EB951872e02e', + USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', + USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', + WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', + YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4', + ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', + USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + }, + }, + ReserveAssets: { + [eEthereumNetwork.coverage]: {}, + [eEthereumNetwork.hardhat]: {}, + [eEthereumNetwork.buidlerevm]: {}, + [EthereumNetwork.main]: {}, + [EthereumNetwork.kovan]: {}, + [EthereumNetwork.ropsten]: {}, + [EthereumNetwork.tenderlyMain]: {}, + }, + ReservesConfig: {}, + ATokenDomainSeparator: { + [eEthereumNetwork.coverage]: + '0x95b73a72c6ecf4ccbbba5178800023260bad8e75cdccdb8e4827a2977a37c820', + [eEthereumNetwork.hardhat]: + '0xbae024d959c6a022dc5ed37294cd39c141034b2ae5f02a955cce75c930a81bf5', + [eEthereumNetwork.buidlerevm]: + '0xbae024d959c6a022dc5ed37294cd39c141034b2ae5f02a955cce75c930a81bf5', + [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, + WETH: { + [eEthereumNetwork.coverage]: '', // deployed in local evm + [eEthereumNetwork.hardhat]: '', // deployed in local evm + [eEthereumNetwork.buidlerevm]: '', // deployed in local evm + [eEthereumNetwork.kovan]: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', + [eEthereumNetwork.ropsten]: '0xc778417e063141139fce010982780140aa0cd5ab', + [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + [eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + }, + ReserveFactorTreasuryAddress: { + [eEthereumNetwork.coverage]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.hardhat]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.buidlerevm]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.kovan]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.ropsten]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.main]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.tenderlyMain]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + }, +}; diff --git a/markets/uniswap/index.ts b/markets/uniswap/index.ts new file mode 100644 index 00000000..37daa4af --- /dev/null +++ b/markets/uniswap/index.ts @@ -0,0 +1,88 @@ +import { oneRay, ZERO_ADDRESS } from '../../helpers/constants'; +import { IUniswapConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; + +import { CommonsConfig } from './commons'; +import { + strategyDAI, + strategyUSDC, + strategyUSDT, + strategyWETH, + strategyWBTC, + strategyWETHWBTC, + strategyWETHDAI +} from './reservesConfigs'; + +// ---------------- +// POOL--SPECIFIC PARAMS +// ---------------- + +export const UniswapConfig: IUniswapConfiguration = { + ...CommonsConfig, + MarketId: 'Uniswap V2 market', + ProviderId: 2, + ReservesConfig: { + DAI: strategyDAI, + USDC: strategyUSDC, + USDT: strategyUSDT, + WBTC: strategyWBTC, + WETH: strategyWETH, + WETHDAI: strategyWETHDAI, + WETHWBTC: strategyWETHWBTC + }, + ReserveAssets: { + [eEthereumNetwork.buidlerevm]: {}, + [eEthereumNetwork.hardhat]: {}, + [eEthereumNetwork.coverage]: {}, + [EthereumNetwork.kovan]: { + DAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', + USDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', + USDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', + WBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', + WETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', + WETHDAI: '', + WETHWBTC: '', + }, + [EthereumNetwork.ropsten]: { + // AAVE: '', + // BAT: '0x85B24b3517E3aC7bf72a14516160541A60cFF19d', + // BUSD: '0xFA6adcFf6A90c11f31Bc9bb59eC0a6efB38381C6', + // DAI: '0xf80A32A835F79D7787E8a8ee5721D0fEaFd78108', + // ENJ: ZERO_ADDRESS, + // KNC: '0xCe4aA1dE3091033Ba74FA2Ad951f6adc5E5cF361', + // LINK: '0x1a906E71FF9e28d8E01460639EB8CF0a6f0e2486', + // MANA: '0x78b1F763857C8645E46eAdD9540882905ff32Db7', + // MKR: '0x2eA9df3bABe04451c9C3B06a2c844587c59d9C37', + // REN: ZERO_ADDRESS, + // SNX: '0xF80Aa7e2Fda4DA065C55B8061767F729dA1476c7', + // SUSD: '0xc374eB17f665914c714Ac4cdC8AF3a3474228cc5', + // TUSD: '0xa2EA00Df6d8594DBc76b79beFe22db9043b8896F', + // UNI: ZERO_ADDRESS, + // USDC: '0x851dEf71f0e6A903375C1e536Bd9ff1684BAD802', + // USDT: '0xB404c51BBC10dcBE948077F18a4B8E553D160084', + // WBTC: '0xa0E54Ab6AA5f0bf1D62EC3526436F3c05b3348A0', + // WETH: '0xc778417e063141139fce010982780140aa0cd5ab', + // YFI: ZERO_ADDRESS, + // ZRX: '0x02d7055704EfF050323A2E5ee4ba05DB2A588959', + }, + [EthereumNetwork.main]: { + DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + WETHDAI: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', + WETHWBTC: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', + }, + [EthereumNetwork.tenderlyMain]: { + DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + WETHDAI: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', + WETHWBTC: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', + }, + }, +}; + +export default UniswapConfig; diff --git a/markets/uniswap/reservesConfigs.ts b/markets/uniswap/reservesConfigs.ts new file mode 100644 index 00000000..caeaba46 --- /dev/null +++ b/markets/uniswap/reservesConfigs.ts @@ -0,0 +1,122 @@ +import BigNumber from 'bignumber.js'; +import { oneRay } from '../../helpers/constants'; +import { eContractid, IReserveParams } from '../../helpers/types'; + +export const strategyWETH: IReserveParams = { + 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(), + baseLTVAsCollateral: '8000', + liquidationThreshold: '8250', + liquidationBonus: '10500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000' +}; + +export const strategyWBTC: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + 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(), + baseLTVAsCollateral: '7000', + liquidationThreshold: '7500', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '8', + aTokenImpl: eContractid.AToken, + reserveFactor: '2000' +}; + +export const strategyDAI: IReserveParams = { + 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(), + baseLTVAsCollateral: '7500', + liquidationThreshold: '8000', + liquidationBonus: '10500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000' +}; + +export const strategyUSDC: IReserveParams = { + 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(), + baseLTVAsCollateral: '8000', + liquidationThreshold: '8500', + liquidationBonus: '10500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '6', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000' +}; + +export const strategyUSDT: IReserveParams = { + 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(), + baseLTVAsCollateral: '8000', + liquidationThreshold: '8500', + liquidationBonus: '10500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '6', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000' +}; + +export const strategyWETHDAI: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '5000', + liquidationThreshold: '6500', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000' +}; + +export const strategyWETHWBTC: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '5000', + liquidationThreshold: '6500', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000' +}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 32738e30..dfdeb1a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2908,15 +2908,6 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, - "bufferutil": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.2.tgz", - "integrity": "sha512-AtnG3W6M8B2n4xDQ5R+70EXvOpnXsFYg/AK2yTZd+HQ/oxAdz+GI+DvjmhBw3L0ole+LJ0ngqY4JMbDzkfNzhA==", - "dev": true, - "requires": { - "node-gyp-build": "^4.2.0" - } - }, "buidler-typechain": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/buidler-typechain/-/buidler-typechain-0.1.1.tgz", @@ -3111,33 +3102,6 @@ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, - "cids": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", - "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", - "dev": true, - "optional": true, - "requires": { - "buffer": "^5.5.0", - "class-is": "^1.1.0", - "multibase": "~0.6.0", - "multicodec": "^1.0.0", - "multihashes": "~0.4.15" - }, - "dependencies": { - "multicodec": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", - "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", - "dev": true, - "optional": true, - "requires": { - "buffer": "^5.6.0", - "varint": "^5.0.0" - } - } - } - }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3148,13 +3112,6 @@ "safe-buffer": "^5.0.1" } }, - "class-is": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", - "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", - "dev": true, - "optional": true - }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -3257,6 +3214,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "requires": { "color-name": "1.1.3" } @@ -3264,7 +3222,8 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true }, "colors": { "version": "1.4.0", @@ -3398,18 +3357,6 @@ } } }, - "content-hash": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", - "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", - "dev": true, - "optional": true, - "requires": { - "cids": "^0.7.1", - "multicodec": "^0.5.5", - "multihashes": "^0.4.15" - } - }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", @@ -6352,6 +6299,148 @@ "@ethersproject/strings": ">=5.0.0-beta.130" } }, + "@ethersproject/address": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.5.tgz", + "integrity": "sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/rlp": "^5.0.3", + "bn.js": "^4.4.0" + } + }, + "@ethersproject/bignumber": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.8.tgz", + "integrity": "sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "bn.js": "^4.4.0" + } + }, + "@ethersproject/bytes": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.5.tgz", + "integrity": "sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/constants": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.5.tgz", + "integrity": "sha512-foaQVmxp2+ik9FrLUCtVrLZCj4M3Ibgkqvh+Xw/vFRSerkjVSYePApaVE5essxhoSlF1U9oXfWY09QI2AXtgKA==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bignumber": "^5.0.7" + } + }, + "@ethersproject/hash": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.5.tgz", + "integrity": "sha512-GpI80/h2HDpfNKpCZoxQJCjOQloGnlD5hM1G+tZe8FQDJhEvFjJoPDuWv+NaYjJfOciKS2Axqc4Q4WamdLoUgg==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/strings": "^5.0.4" + } + }, + "@ethersproject/keccak256": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.4.tgz", + "integrity": "sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.4", + "js-sha3": "0.5.7" + } + }, + "@ethersproject/logger": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.6.tgz", + "integrity": "sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ==", + "dev": true, + "optional": true + }, + "@ethersproject/properties": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.4.tgz", + "integrity": "sha512-UdyX3GqBxFt15B0uSESdDNmhvEbK3ACdDXl2soshoPcneXuTswHDeA0LoPlnaZzhbgk4p6jqb4GMms5C26Qu6A==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/rlp": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.4.tgz", + "integrity": "sha512-5qrrZad7VTjofxSsm7Zg/7Dr4ZOln4S2CqiDdOuTv6MBKnXj0CiBojXyuDy52M8O3wxH0CyE924hXWTDV1PQWQ==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/signing-key": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.5.tgz", + "integrity": "sha512-Z1wY7JC1HVO4CvQWY2TyTTuAr8xK3bJijZw1a9G92JEmKdv1j255R/0YLBBcFTl2J65LUjtXynNJ2GbArPGi5g==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "elliptic": "6.5.3" + } + }, + "@ethersproject/strings": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.5.tgz", + "integrity": "sha512-JED6WaIV00xM/gvj8vSnd+0VWtDYdidTmavFRCTQakqfz+4tDo6Jz5LHgG+dd45h7ah7ykCHW0C7ZXWEDROCXQ==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/transactions": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.6.tgz", + "integrity": "sha512-htsFhOD+NMBxx676A8ehSuwVV49iqpSB+CkjPZ02tpNew0K6p8g0CZ46Z1ZP946gIHAU80xQ0NACHYrjIUaCFA==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/rlp": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4" + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -6369,14 +6458,6 @@ "defer-to-connect": "^1.0.1" } }, - "@types/bignumber.js": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/bignumber.js/-/bignumber.js-5.0.0.tgz", - "integrity": "sha512-0DH7aPGCClywOFaxxjE6UwpN2kQYe9LwuDQMv+zYA97j5GkOMo8e66LYT+a8JYU7jfmUFRZLa9KycxHDsKXJCA==", - "requires": { - "bignumber.js": "*" - } - }, "@types/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", @@ -6410,53 +6491,11 @@ "@types/node": "*" } }, - "@web3-js/scrypt-shim": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz", - "integrity": "sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw==", - "requires": { - "scryptsy": "^2.1.0", - "semver": "^6.3.0" - }, - "dependencies": { - "scryptsy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz", - "integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==" - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "@web3-js/websocket": { - "version": "1.0.30", - "resolved": "https://registry.npmjs.org/@web3-js/websocket/-/websocket-1.0.30.tgz", - "integrity": "sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA==", - "requires": { - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "nan": "^2.14.0", - "typedarray-to-buffer": "^3.1.5", - "yaeti": "^0.0.6" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true }, "abstract-leveldown": { "version": "3.0.0", @@ -6497,112 +6536,32 @@ "uri-js": "^4.2.2" } }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" - }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "requires": { - "make-iterator": "^1.0.0" - } + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "requires": { - "make-iterator": "^1.0.0" - } + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true }, "array-flatten": { "version": "1.1.1", @@ -6611,63 +6570,11 @@ "dev": true, "optional": true }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true }, "asn1": { "version": "0.2.4", @@ -6700,7 +6607,8 @@ "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true }, "async": { "version": "2.6.2", @@ -6711,22 +6619,6 @@ "lodash": "^4.17.11" } }, - "async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" - }, "async-eventemitter": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", @@ -6742,14 +6634,6 @@ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "dev": true }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "requires": { - "async-done": "^1.2.2" - } - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -6759,7 +6643,8 @@ "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true }, "aws-sign2": { "version": "0.7.0", @@ -6784,6 +6669,12 @@ "js-tokens": "^3.0.2" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -6809,6 +6700,15 @@ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", "dev": true }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -6853,16 +6753,22 @@ "ms": "2.0.0" } }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", "dev": true } } @@ -6888,12 +6794,6 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true } } }, @@ -7406,21 +7306,6 @@ "source-map-support": "^0.4.15" }, "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "source-map-support": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", @@ -7481,6 +7366,12 @@ "ms": "2.0.0" } }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -7499,6 +7390,14 @@ "esutils": "^2.0.2", "lodash": "^4.17.4", "to-fast-properties": "^1.0.3" + }, + "dependencies": { + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + } } }, "babelify": { @@ -7517,22 +7416,6 @@ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, "backoff": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", @@ -7545,12 +7428,14 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, "requires": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", @@ -7565,35 +7450,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "^1.0.0" } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } } } }, @@ -7601,6 +7461,7 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", + "dev": true, "requires": { "safe-buffer": "^5.0.1" } @@ -7608,7 +7469,8 @@ "base64-js": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -7630,20 +7492,9 @@ "bignumber.js": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", - "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "requires": { - "file-uri-to-path": "1.0.0" - } + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", + "dev": true, + "optional": true }, "bip39": { "version": "2.5.0", @@ -7658,66 +7509,6 @@ "unorm": "^1.3.3" } }, - "bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "bl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - } - } - }, "blakejs": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", @@ -7734,7 +7525,8 @@ "bn.js": { "version": "4.11.9", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true }, "body-parser": { "version": "1.19.0", @@ -7785,44 +7577,23 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" - } - } - }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true }, "browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, "requires": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -7921,6 +7692,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "dev": true, "requires": { "base-x": "^3.0.2" } @@ -7929,6 +7701,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, "requires": { "bs58": "^4.0.0", "create-hash": "^1.1.0", @@ -7939,44 +7712,17 @@ "version": "5.6.0", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dev": true, "requires": { "base64-js": "^1.0.2", "ieee754": "^1.1.4" } }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=" - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" - }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true }, "buffer-to-arraybuffer": { "version": "0.0.5", @@ -7988,7 +7734,25 @@ "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "bufferutil": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", + "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==", + "dev": true, + "requires": { + "node-gyp-build": "~3.7.0" + }, + "dependencies": { + "node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "dev": true + } + } }, "bytes": { "version": "3.1.0", @@ -8020,6 +7784,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, "requires": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", @@ -8048,16 +7813,6 @@ "responselike": "^1.0.2" }, "dependencies": { - "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", - "dev": true, - "optional": true, - "requires": { - "pump": "^3.0.0" - } - }, "lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -8097,11 +7852,6 @@ } } }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" - }, "caniuse-lite": { "version": "1.0.30001146", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001146.tgz", @@ -8118,6 +7868,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -8133,24 +7884,6 @@ "functional-red-black-tree": "^1.0.1" } }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, "chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -8158,19 +7891,61 @@ "dev": true, "optional": true }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cids": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", + "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", + "dev": true, + "optional": true, + "requires": { + "buffer": "^5.5.0", + "class-is": "^1.1.0", + "multibase": "~0.6.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.15" + }, + "dependencies": { + "multicodec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", + "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", + "dev": true, + "optional": true, + "requires": { + "buffer": "^5.6.0", + "varint": "^5.0.0" + } + } + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, + "class-is": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", + "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", + "dev": true, + "optional": true + }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, "requires": { "arr-union": "^3.1.0", "define-property": "^0.2.5", @@ -8181,29 +7956,82 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=" + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true } } }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, "clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true }, "clone-response": { "version": "1.0.2", @@ -8215,83 +8043,30 @@ "mimic-response": "^1.0.0" } }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" - }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, "requires": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" } }, - "color-support": { + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true }, "combined-stream": { "version": "1.0.8", @@ -8302,64 +8077,28 @@ "delayed-stream": "~1.0.0" } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, "requires": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "content-disposition": { @@ -8381,6 +8120,18 @@ } } }, + "content-hash": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", + "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", + "dev": true, + "optional": true, + "requires": { + "cids": "^0.7.1", + "multicodec": "^0.5.5", + "multihashes": "^0.4.15" + } + }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", @@ -8392,6 +8143,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, "requires": { "safe-buffer": "~5.1.1" }, @@ -8399,7 +8151,8 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, @@ -8427,16 +8180,8 @@ "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" - }, - "copy-props": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", - "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", - "requires": { - "each-props": "^1.3.0", - "is-plain-object": "^2.0.1" - } + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true }, "core-js": { "version": "2.6.11", @@ -8453,7 +8198,8 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "cors": { "version": "2.8.5", @@ -8481,6 +8227,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, "requires": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -8493,6 +8240,7 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, "requires": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -8536,6 +8284,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, "requires": { "es5-ext": "^0.10.50", "type": "^1.0.1" @@ -8559,37 +8308,11 @@ "ms": "^2.1.1" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "decompress": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", - "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", - "requires": { - "decompress-tar": "^4.0.0", - "decompress-tarbz2": "^4.0.0", - "decompress-targz": "^4.0.0", - "decompress-unzip": "^4.0.1", - "graceful-fs": "^4.1.10", - "make-dir": "^1.0.0", - "pify": "^2.3.0", - "strip-dirs": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true }, "decompress-response": { "version": "3.3.0", @@ -8601,77 +8324,6 @@ "mimic-response": "^1.0.0" } }, - "decompress-tar": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", - "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", - "requires": { - "file-type": "^5.2.0", - "is-stream": "^1.1.0", - "tar-stream": "^1.5.2" - } - }, - "decompress-tarbz2": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", - "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", - "requires": { - "decompress-tar": "^4.1.0", - "file-type": "^6.1.0", - "is-stream": "^1.1.0", - "seek-bzip": "^1.0.5", - "unbzip2-stream": "^1.0.9" - }, - "dependencies": { - "file-type": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", - "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" - } - } - }, - "decompress-targz": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", - "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", - "requires": { - "decompress-tar": "^4.1.1", - "file-type": "^5.2.0", - "is-stream": "^1.1.0" - } - }, - "decompress-unzip": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", - "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", - "requires": { - "file-type": "^3.8.0", - "get-stream": "^2.2.0", - "pify": "^2.3.0", - "yauzl": "^2.4.2" - }, - "dependencies": { - "file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" - }, - "get-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", - "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", - "requires": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, "deep-equal": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", @@ -8684,36 +8336,8 @@ "object-is": "^1.0.1", "object-keys": "^1.1.1", "regexp.prototype.flags": "^1.2.0" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } } }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "requires": { - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=" - }, "defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -8725,6 +8349,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", + "dev": true, "requires": { "abstract-leveldown": "~5.0.0", "inherits": "^2.0.3" @@ -8734,6 +8359,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, "requires": { "xtend": "~4.0.0" } @@ -8744,52 +8370,19 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, "requires": { "object-keys": "^1.0.12" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - } } }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } } }, "defined": { @@ -8829,11 +8422,6 @@ "dev": true, "optional": true }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" - }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", @@ -8870,16 +8458,6 @@ "minimatch": "^3.0.4" } }, - "drbg.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", - "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", - "requires": { - "browserify-aes": "^1.0.6", - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4" - } - }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -8887,60 +8465,6 @@ "dev": true, "optional": true }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -8968,6 +8492,7 @@ "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", @@ -9033,6 +8558,7 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "requires": { "once": "^1.4.0" } @@ -9041,22 +8567,16 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, "requires": { "prr": "~1.0.1" } }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, "es-abstract": { "version": "1.17.7", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", @@ -9069,19 +8589,13 @@ "object.assign": "^4.1.1", "string.prototype.trimend": "^1.0.1", "string.prototype.trimstart": "^1.0.1" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - } } }, "es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -9092,6 +8606,7 @@ "version": "0.10.53", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.3", @@ -9102,6 +8617,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, "requires": { "d": "1", "es5-ext": "^0.10.35", @@ -9112,22 +8628,12 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, "requires": { "d": "^1.0.1", "ext": "^1.1.2" } }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -9138,7 +8644,8 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "esutils": { "version": "2.0.3", @@ -9210,15 +8717,6 @@ "requires": { "idna-uts46-hx": "^2.3.1", "js-sha3": "^0.5.7" - }, - "dependencies": { - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true, - "optional": true - } } }, "eth-json-rpc-infura": { @@ -9272,12 +8770,6 @@ "abstract-leveldown": "~2.6.0" } }, - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true - }, "ethereumjs-account": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", @@ -9300,6 +8792,14 @@ "ethereumjs-tx": "^1.2.2", "ethereumjs-util": "^5.0.0", "merkle-patricia-tree": "^2.1.2" + }, + "dependencies": { + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", + "dev": true + } } }, "ethereumjs-tx": { @@ -9310,14 +8810,6 @@ "requires": { "ethereum-common": "^0.0.18", "ethereumjs-util": "^5.0.0" - }, - "dependencies": { - "ethereum-common": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=", - "dev": true - } } }, "ethereumjs-util": { @@ -9504,13 +8996,36 @@ "prr": "~1.0.1", "semver": "~5.4.1", "xtend": "~4.0.0" + } + }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "requires": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" }, "dependencies": { - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "requires": { + "xtend": "~4.0.0" + } } } }, @@ -9544,6 +9059,18 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -9669,12 +9196,6 @@ "abstract-leveldown": "~2.6.0" } }, - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true - }, "ethereumjs-account": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", @@ -9697,6 +9218,14 @@ "ethereumjs-tx": "^1.2.2", "ethereumjs-util": "^5.0.0", "merkle-patricia-tree": "^2.1.2" + }, + "dependencies": { + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", + "dev": true + } } }, "ethereumjs-tx": { @@ -9707,14 +9236,6 @@ "requires": { "ethereum-common": "^0.0.18", "ethereumjs-util": "^5.0.0" - }, - "dependencies": { - "ethereum-common": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=", - "dev": true - } } }, "ethereumjs-util": { @@ -9901,13 +9422,36 @@ "prr": "~1.0.1", "semver": "~5.4.1", "xtend": "~4.0.0" + } + }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "requires": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" }, "dependencies": { - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "requires": { + "xtend": "~4.0.0" + } } } }, @@ -9941,6 +9485,18 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -10200,13 +9756,36 @@ "prr": "~1.0.1", "semver": "~5.4.1", "xtend": "~4.0.0" + } + }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "requires": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" }, "dependencies": { - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "requires": { + "xtend": "~4.0.0" + } } } }, @@ -10240,6 +9819,18 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -10295,34 +9886,6 @@ "ethereum-cryptography": "^0.1.3", "ethjs-util": "0.1.6", "rlp": "^2.2.3" - }, - "dependencies": { - "keccak": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", - "integrity": "sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==", - "requires": { - "bindings": "^1.5.0", - "inherits": "^2.0.4", - "nan": "^2.14.0", - "safe-buffer": "^5.2.0" - } - }, - "secp256k1": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz", - "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", - "requires": { - "bindings": "^1.5.0", - "bip66": "^1.1.5", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "drbg.js": "^1.0.1", - "elliptic": "^6.5.2", - "nan": "^2.14.0", - "safe-buffer": "^5.1.2" - } - } } }, "ethereumjs-vm": { @@ -10459,13 +10022,36 @@ "prr": "~1.0.1", "semver": "~5.4.1", "xtend": "~4.0.0" + } + }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "requires": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" }, "dependencies": { - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "requires": { + "xtend": "~4.0.0" + } } } }, @@ -10514,6 +10100,18 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -10587,6 +10185,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, "requires": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -10596,6 +10195,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, "requires": { "debug": "^2.3.3", "define-property": "^0.2.5", @@ -10610,6 +10210,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -10617,28 +10218,98 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=" + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -10715,6 +10386,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, "requires": { "type": "^2.0.0" }, @@ -10722,38 +10394,32 @@ "type": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==" + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", + "dev": true } } }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, "requires": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } } }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, "requires": { "array-unique": "^0.3.2", "define-property": "^1.0.0", @@ -10769,6 +10435,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -10776,33 +10443,17 @@ "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { - "kind-of": "^6.0.0" + "is-extendable": "^0.1.0" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true } } }, @@ -10821,17 +10472,6 @@ "checkpoint-store": "^1.1.0" } }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -10844,14 +10484,6 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "requires": { - "pend": "~1.2.0" - } - }, "fetch-ponyfill": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz", @@ -10861,6 +10493,12 @@ "node-fetch": "~1.7.1" }, "dependencies": { + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", @@ -10873,34 +10511,6 @@ } } }, - "file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" - } - } - }, "finalhandler": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", @@ -10936,92 +10546,150 @@ } } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "find-yarn-workspace-root": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz", + "integrity": "sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==", + "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "fs-extra": "^4.0.3", + "micromatch": "^3.1.4" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } } }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" - }, "flow-stoplight": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz", "integrity": "sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s=", "dev": true }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -11034,15 +10702,8 @@ "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "requires": { - "for-in": "^1.0.1" - } + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true }, "forever-agent": { "version": "0.6.1", @@ -11072,6 +10733,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, "requires": { "map-cache": "^0.2.2" } @@ -11083,64 +10745,41 @@ "dev": true, "optional": true }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, "fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true }, "get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "optional": true, "requires": { "pump": "^3.0.0" } @@ -11148,7 +10787,8 @@ "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true }, "getpass": { "version": "0.1.7", @@ -11163,6 +10803,7 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -11172,90 +10813,6 @@ "path-is-absolute": "^1.0.0" } }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - } - }, "global": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", @@ -11264,42 +10821,14 @@ "requires": { "min-document": "^2.19.0", "process": "~0.5.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "requires": { - "sparkles": "^1.0.0" + }, + "dependencies": { + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", + "dev": true + } } }, "got": { @@ -11337,53 +10866,8 @@ "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" - }, - "gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - }, - "dependencies": { - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - } - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "requires": { - "glogg": "^1.0.0" - } + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true }, "har-schema": { "version": "2.0.0", @@ -11405,6 +10889,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -11416,8 +10901,22 @@ "dev": true, "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, "has-symbol-support-x": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", @@ -11428,7 +10927,8 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true }, "has-to-string-tag-x": { "version": "1.4.1", @@ -11444,6 +10944,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, "requires": { "get-value": "^2.0.6", "has-values": "^1.0.0", @@ -11454,15 +10955,43 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, "requires": { "is-number": "^3.0.0", "kind-of": "^4.0.0" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -11473,6 +11002,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, "requires": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -11483,6 +11013,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -11495,38 +11026,12 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, "requires": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, - "hdkey": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-1.1.2.tgz", - "integrity": "sha512-PTQ4VKu0oRnCrYfLp04iQZ7T2Cxz0UsEXYauk2j8eh6PJXCpbXuCFhOmtIFtbET0i3PMWmHN9J11gU8LEgUljQ==", - "requires": { - "bs58check": "^2.1.2", - "safe-buffer": "^5.1.1", - "secp256k1": "^3.0.1" - }, - "dependencies": { - "secp256k1": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz", - "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", - "requires": { - "bindings": "^1.5.0", - "bip66": "^1.1.5", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "drbg.js": "^1.0.1", - "elliptic": "^6.5.2", - "nan": "^2.14.0", - "safe-buffer": "^5.1.2" - } - } - } - }, "heap": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", @@ -11537,6 +11042,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, "requires": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -11553,19 +11059,6 @@ "os-tmpdir": "^1.0.1" } }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" - }, "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -11646,17 +11139,20 @@ "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true }, "immediate": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", + "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -11665,17 +11161,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "invariant": { "version": "2.2.4", @@ -11686,11 +11173,6 @@ "loose-envify": "^1.0.0" } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" - }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -11698,28 +11180,13 @@ "dev": true, "optional": true }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "dev": true, + "requires": { + "kind-of": "^6.0.0" } }, "is-arguments": { @@ -11728,78 +11195,56 @@ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", "dev": true }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "is-callable": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "dev": true, + "requires": { + "kind-of": "^6.0.0" } }, "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } }, "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, "requires": { "is-plain-object": "^2.0.4" } }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, "is-finite": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", @@ -11812,61 +11257,23 @@ "integrity": "sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw=", "dev": true }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, "is-function": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", "dev": true }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, "is-hex-prefixed": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", "dev": true }, - "is-natural-number": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", - "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=" - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true }, "is-object": { "version": "1.0.1", @@ -11886,6 +11293,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, "requires": { "isobject": "^3.0.1" } @@ -11894,18 +11302,11 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, "requires": { "has-symbols": "^1.0.1" } }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "requires": { - "is-unc-path": "^1.0.0" - } - }, "is-retry-allowed": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", @@ -11913,15 +11314,11 @@ "dev": true, "optional": true }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, "is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -11929,30 +11326,14 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=" + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true }, "isarray": { "version": "1.0.0", @@ -11963,12 +11344,14 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true }, "isstream": { "version": "0.1.2", @@ -11990,7 +11373,9 @@ "js-sha3": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true, + "optional": true }, "js-tokens": { "version": "4.0.0", @@ -12004,12 +11389,6 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -12067,27 +11446,17 @@ "jsonify": "~0.0.0" } }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" - }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, "requires": { "graceful-fs": "^4.1.6" } @@ -12110,11 +11479,6 @@ "verror": "1.10.0" } }, - "just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=" - }, "keccak": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", @@ -12138,73 +11502,16 @@ "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "requires": { - "readable-stream": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "requires": { - "invert-kv": "^1.0.0" - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "requires": { - "flush-write-stream": "^1.0.2" + "graceful-fs": "^4.1.11" } }, "level-codec": { @@ -12229,34 +11536,11 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz", "integrity": "sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig==", + "dev": true, "requires": { "inherits": "^2.0.1", + "readable-stream": "^2.0.5", "xtend": "^4.0.0" - }, - "dependencies": { - "level-errors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.1.2.tgz", - "integrity": "sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w==", - "requires": { - "errno": "~0.1.1" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } } }, "level-mem": { @@ -12278,12 +11562,6 @@ "xtend": "~4.0.0" } }, - "immediate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", - "dev": true - }, "ltgt": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", @@ -12347,61 +11625,6 @@ "pull-stream": "^3.6.8", "typewiselite": "~1.0.0", "xtend": "~4.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "level-iterator-stream": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz", - "integrity": "sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.5", - "xtend": "^4.0.0" - } - }, - "ltgt": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.1.3.tgz", - "integrity": "sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "level-ws": { @@ -12413,35 +11636,6 @@ "inherits": "^2.0.3", "readable-stream": "^2.2.8", "xtend": "^4.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - } } }, "levelup": { @@ -12456,31 +11650,6 @@ "xtend": "~4.0.0" }, "dependencies": { - "abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "dev": true, - "requires": { - "xtend": "~4.0.0" - } - }, - "deferred-leveldown": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", - "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", - "dev": true, - "requires": { - "abstract-leveldown": "~5.0.0", - "inherits": "^2.0.3" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, "level-iterator-stream": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", @@ -12491,70 +11660,6 @@ "readable-stream": "^2.3.6", "xtend": "^4.0.0" } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, @@ -12601,78 +11706,26 @@ "integrity": "sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ=", "dev": true }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" - } - } - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "requires": { - "kind-of": "^6.0.2" - } - }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, "requires": { "object-visit": "^1.0.0" } }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "dependencies": { - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -12708,23 +11761,6 @@ "semaphore": ">=1.0.1" }, "dependencies": { - "abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "requires": { - "xtend": "~4.0.0" - } - }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, "ethereumjs-util": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", @@ -12740,55 +11776,6 @@ "safe-buffer": "^5.1.1" } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "level-codec": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", - "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==" - }, - "level-errors": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", - "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", - "requires": { - "errno": "~0.1.1" - } - }, - "levelup": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", - "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", - "requires": { - "level-codec": "~7.0.0", - "level-errors": "~1.0.3", - "prr": "~1.0.1", - "semver": "~5.4.1", - "xtend": "~4.0.0" - } - }, - "memdown": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", - "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", - "requires": { - "abstract-leveldown": "~2.7.1", - "functional-red-black-tree": "^1.0.1", - "immediate": "^3.2.3", - "inherits": "~2.0.1", - "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -12798,35 +11785,6 @@ "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } } } } @@ -12838,26 +11796,6 @@ "dev": true, "optional": true }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -12909,17 +11847,20 @@ "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true }, "minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -12930,17 +11871,6 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, "minizlib": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", @@ -12949,25 +11879,29 @@ "optional": true, "requires": { "minipass": "^2.9.0" + }, + "dependencies": { + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + } } }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } } }, "mkdirp": { @@ -12975,7 +11909,6 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, - "optional": true, "requires": { "minimist": "^1.2.5" } @@ -13003,15 +11936,51 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==" + "multibase": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", + "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", + "dev": true, + "optional": true, + "requires": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" + "multicodec": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", + "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", + "dev": true, + "optional": true, + "requires": { + "varint": "^5.0.0" + } + }, + "multihashes": { + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", + "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", + "dev": true, + "optional": true, + "requires": { + "buffer": "^5.5.0", + "multibase": "^0.7.0", + "varint": "^5.0.0" + }, + "dependencies": { + "multibase": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", + "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", + "dev": true, + "optional": true, + "requires": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + } + } }, "nano-json-stream-parser": { "version": "0.1.2", @@ -13024,6 +11993,7 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -13048,7 +12018,14 @@ "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true }, "node-addon-api": { "version": "2.0.2", @@ -13068,29 +12045,6 @@ "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", "dev": true }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, "normalize-url": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", @@ -13098,19 +12052,6 @@ "dev": true, "optional": true }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "requires": { - "once": "^1.3.2" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, "number-to-bn": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", @@ -13140,12 +12081,14 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true }, "object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, "requires": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", @@ -13155,12 +12098,60 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=" + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -13170,7 +12161,8 @@ "object-inspect": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true }, "object-is": { "version": "1.1.3", @@ -13214,6 +12206,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, "requires": { "isobject": "^3.0.0" } @@ -13222,6 +12215,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.18.0-next.0", @@ -13233,6 +12227,7 @@ "version": "1.18.0-next.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", @@ -13247,25 +12242,9 @@ "string.prototype.trimend": "^1.0.1", "string.prototype.trimstart": "^1.0.1" } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" } } }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, "object.getownpropertydescriptors": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", @@ -13276,32 +12255,15 @@ "es-abstract": "^1.17.0-next.1" } }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, "requires": { "isobject": "^3.0.1" } }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, "oboe": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.4.tgz", @@ -13326,66 +12288,17 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "requires": { - "readable-stream": "^2.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "requires": { - "lcid": "^1.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -13399,13 +12312,6 @@ "dev": true, "optional": true }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "optional": true - }, "p-timeout": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", @@ -13414,6 +12320,15 @@ "optional": true, "requires": { "p-finally": "^1.0.0" + }, + "dependencies": { + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "optional": true + } } }, "parse-asn1": { @@ -13430,40 +12345,12 @@ "safe-buffer": "^5.1.1" } }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, "parse-headers": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==", "dev": true }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==" - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" - }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -13474,43 +12361,106 @@ "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "patch-package": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.2.2.tgz", + "integrity": "sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg==", + "dev": true, "requires": { - "pinkie-promise": "^2.0.0" + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "find-yarn-workspace-root": "^1.2.1", + "fs-extra": "^7.0.1", + "is-ci": "^2.0.0", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.0", + "rimraf": "^2.6.3", + "semver": "^5.6.0", + "slash": "^2.0.0", + "tmp": "^0.0.33" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true }, "path-to-regexp": { "version": "0.1.7", @@ -13519,27 +12469,11 @@ "dev": true, "optional": true }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, "pbkdf2": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, "requires": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -13548,34 +12482,17 @@ "sha.js": "^2.4.8" } }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" - } - }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true }, "precond": { "version": "0.2.3", @@ -13590,27 +12507,17 @@ "dev": true, "optional": true }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" - }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true - }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true }, "promise-to-callback": { "version": "1.0.0", @@ -13636,7 +12543,8 @@ "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true }, "pseudomap": { "version": "1.0.2", @@ -13727,32 +12635,13 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "optional": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -13762,7 +12651,8 @@ "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true }, "query-string": { "version": "5.1.1", @@ -13816,25 +12706,6 @@ "unpipe": "1.0.0" } }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -13858,58 +12729,6 @@ } } }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "requires": { - "resolve": "^1.1.6" - } - }, "regenerate": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", @@ -13937,6 +12756,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" @@ -13976,41 +12796,27 @@ "dev": true, "requires": { "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } } }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true }, "repeating": { "version": "2.0.1", @@ -14021,21 +12827,6 @@ "is-finite": "^1.0.0" } }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==" - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -14062,55 +12853,22 @@ "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - } } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" - }, "resolve": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, "requires": { "path-parse": "^1.0.6" } }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "requires": { - "value-or-function": "^3.0.0" - } - }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true }, "responselike": { "version": "1.0.2", @@ -14134,7 +12892,8 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true }, "rimraf": { "version": "2.6.3", @@ -14149,6 +12908,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -14172,7 +12932,8 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true }, "safe-event-emitter": { "version": "1.0.1", @@ -14187,6 +12948,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, "requires": { "ret": "~0.1.10" } @@ -14203,18 +12965,12 @@ "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", "dev": true }, - "scrypt.js": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.3.0.tgz", - "integrity": "sha512-42LTc1nyFsyv/o0gcHtDztrn+aqpkaCNt5Qh7ATBZfhEZU7IC/0oT/qbBH+uRNoAPvs2fwiOId68FDEoSRA8/A==", - "requires": { - "scryptsy": "^1.2.1" - } - }, "scryptsy": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", + "dev": true, + "optional": true, "requires": { "pbkdf2": "^3.0.3" } @@ -14236,28 +12992,12 @@ "integrity": "sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg==", "dev": true }, - "seek-bzip": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", - "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", - "requires": { - "commander": "^2.8.1" - } - }, "semaphore": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", "dev": true }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "requires": { - "sver-compat": "^1.5.0" - } - }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -14335,11 +13075,6 @@ "xhr": "^2.3.3" } }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, "set-immediate-shim": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", @@ -14350,8 +13085,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, "requires": { "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", "is-plain-object": "^2.0.3", "split-string": "^3.0.1" }, @@ -14359,7 +13096,17 @@ "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true } } }, @@ -14380,6 +13127,7 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -14404,16 +13152,11 @@ "simple-concat": "^1.0.0" } }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, "requires": { "base": "^0.11.1", "debug": "^2.2.0", @@ -14429,6 +13172,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -14436,22 +13180,95 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=" + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -14459,6 +13276,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, "requires": { "define-property": "^1.0.0", "isobject": "^3.0.0", @@ -14469,35 +13287,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "^1.0.0" } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } } } }, @@ -14505,14 +13298,22 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, "requires": { "kind-of": "^3.2.0" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -14522,12 +13323,14 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true }, "source-map-resolve": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, "requires": { "atob": "^2.1.2", "decode-uri-component": "^0.2.0", @@ -14557,45 +13360,14 @@ "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==" - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, "requires": { "extend-shallow": "^3.0.0" } @@ -14625,15 +13397,11 @@ } } }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, "requires": { "define-property": "^0.2.5", "object-copy": "^0.1.0" @@ -14642,7 +13410,74 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=" + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true } } }, @@ -14653,16 +13488,6 @@ "dev": true, "optional": true }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==" - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" - }, "stream-to-pull-stream": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz", @@ -14688,16 +13513,6 @@ "dev": true, "optional": true }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, "string.prototype.trim": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.2.tgz", @@ -14734,6 +13549,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -14743,6 +13559,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -14752,6 +13569,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, "requires": { "safe-buffer": "~5.1.0" }, @@ -14759,34 +13577,11 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", - "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", - "requires": { - "is-natural-number": "^4.0.1" - } - }, "strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -14800,19 +13595,11 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, "swarm-js": { "version": "0.1.40", "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.40.tgz", @@ -14875,6 +13662,13 @@ "url-to-options": "^1.0.1" } }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "optional": true + }, "p-cancelable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", @@ -14971,62 +13765,25 @@ "yallist": "^3.0.3" }, "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, "optional": true, "requires": { - "minimist": "^1.2.5" - } - } - } - }, - "tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "minipass": "^2.6.0" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "optional": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" } } } @@ -15034,65 +13791,19 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, "requires": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" - }, "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", @@ -15109,38 +13820,26 @@ "rimraf": "^2.6.3" } }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, "requires": { "kind-of": "^3.0.2" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -15158,6 +13857,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, "requires": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", @@ -15165,23 +13865,6 @@ "safe-regex": "^1.1.0" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "requires": { - "through2": "^2.0.3" - } - }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", @@ -15229,7 +13912,8 @@ "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true }, "type-is": { "version": "1.6.18", @@ -15245,12 +13929,14 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, "requires": { "is-typedarray": "^1.0.0" } @@ -15283,20 +13969,6 @@ "dev": true, "optional": true }, - "unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "requires": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" - }, "underscore": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", @@ -15304,50 +13976,31 @@ "dev": true, "optional": true }, - "undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=" - }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", + "is-extendable": "^0.1.1", "set-value": "^2.0.1" - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" + }, + "dependencies": { + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + } } }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true }, "unorm": { "version": "1.6.0", @@ -15366,6 +14019,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, "requires": { "has-value": "^0.3.1", "isobject": "^3.0.0" @@ -15375,6 +14029,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, "requires": { "get-value": "^2.0.3", "has-values": "^0.1.4", @@ -15385,6 +14040,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, "requires": { "isarray": "1.0.0" } @@ -15394,20 +14050,11 @@ "has-values": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true } } }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" - }, "uri-js": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", @@ -15420,7 +14067,8 @@ "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true }, "url-parse-lax": { "version": "3.0.0", @@ -15449,7 +14097,25 @@ "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "utf-8-validate": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz", + "integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==", + "dev": true, + "requires": { + "node-gyp-build": "~3.7.0" + }, + "dependencies": { + "node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "dev": true + } + } }, "utf8": { "version": "3.0.0", @@ -15461,7 +14127,8 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true }, "util.promisify": { "version": "1.0.1", @@ -15488,27 +14155,12 @@ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=" + "varint": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", + "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", + "dev": true, + "optional": true }, "vary": { "version": "1.1.2", @@ -15528,101 +14180,6 @@ "extsprintf": "^1.2.0" } }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, "web3": { "version": "1.2.11", "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.11.tgz", @@ -15637,13 +14194,6 @@ "web3-net": "1.2.11", "web3-shh": "1.2.11", "web3-utils": "1.2.11" - }, - "dependencies": { - "@types/node": { - "version": "12.12.53", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.53.tgz", - "integrity": "sha512-51MYTDTyCziHb70wtGNFRwB4l+5JNvdqzFSkbDvpbftEgVUBEE+T5f7pROhWMp/fxp07oNIEQZd5bbfAH22ohQ==" - } } }, "web3-bzz": { @@ -15788,75 +14338,6 @@ "@ethersproject/abi": "5.0.0-beta.153", "underscore": "1.9.1", "web3-utils": "1.2.11" - }, - "dependencies": { - "@types/node": { - "version": "10.17.28", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.28.tgz", - "integrity": "sha512-dzjES1Egb4c1a89C7lKwQh8pwjYmlOAG9dW1pBgxEk57tMrLnssOfEthz8kdkNaBd7lIqQx7APm5+mZ619IiCQ==" - }, - "aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" - }, - "elliptic": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", - "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" - } - }, - "ethers": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", - "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", - "requires": { - "@types/node": "^10.3.2", - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "elliptic": "6.3.3", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.3", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" - }, - "scrypt-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", - "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=" - }, - "setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" - }, - "uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" - } } }, "web3-eth-accounts": { @@ -15945,15 +14426,6 @@ "requires": { "bn.js": "^4.11.9", "web3-utils": "1.2.11" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true, - "optional": true - } } }, "web3-eth-personal": { @@ -16048,12 +14520,6 @@ "ethereumjs-util": "^5.1.1" } }, - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true - }, "ethereumjs-abi": { "version": "git+https://git@github.com/ethereumjs/ethereumjs-abi.git#1ce6a1d64235fabe2aaf827fd606def55693508f", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", @@ -16102,6 +14568,14 @@ "ethereumjs-tx": "^1.2.2", "ethereumjs-util": "^5.0.0", "merkle-patricia-tree": "^2.1.2" + }, + "dependencies": { + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", + "dev": true + } } }, "ethereumjs-tx": { @@ -16112,14 +14586,6 @@ "requires": { "ethereum-common": "^0.0.18", "ethereumjs-util": "^5.0.0" - }, - "dependencies": { - "ethereum-common": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=", - "dev": true - } } }, "ethereumjs-util": { @@ -16306,13 +14772,36 @@ "prr": "~1.0.1", "semver": "~5.4.1", "xtend": "~4.0.0" + } + }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "requires": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" }, "dependencies": { - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "requires": { + "xtend": "~4.0.0" + } } } }, @@ -16346,56 +14835,23 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } + "dev": true }, "ws": { "version": "5.2.2", @@ -16474,13 +14930,6 @@ "utf8": "3.0.0" }, "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true, - "optional": true - }, "eth-lib": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", @@ -16532,32 +14981,11 @@ "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==", "dev": true }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "ws": { "version": "3.3.3", @@ -16628,69 +15056,23 @@ "cookiejar": "^2.1.1" } }, - "xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true }, "yaeti": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", + "dev": true }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true - }, - "yargs": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", - "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "5.0.0-security.0" - } - }, - "yargs-parser": { - "version": "5.0.0-security.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", - "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } } } }, @@ -17086,7 +15468,8 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, "has-symbol-support-x": { "version": "1.4.2", @@ -17652,7 +16035,8 @@ "is-negative-zero": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=" + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true }, "is-number": { "version": "7.0.0", @@ -18963,52 +17347,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "multibase": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", - "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", - "dev": true, - "optional": true, - "requires": { - "base-x": "^3.0.8", - "buffer": "^5.5.0" - } - }, - "multicodec": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", - "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", - "dev": true, - "optional": true, - "requires": { - "varint": "^5.0.0" - } - }, - "multihashes": { - "version": "0.4.21", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", - "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", - "dev": true, - "optional": true, - "requires": { - "buffer": "^5.5.0", - "multibase": "^0.7.0", - "varint": "^5.0.0" - }, - "dependencies": { - "multibase": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", - "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", - "dev": true, - "optional": true, - "requires": { - "base-x": "^3.0.8", - "buffer": "^5.5.0" - } - } - } - }, "multimatch": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", @@ -22138,15 +20476,6 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, - "utf-8-validate": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.3.tgz", - "integrity": "sha512-jtJM6fpGv8C1SoH4PtG22pGto6x+Y8uPprW0tw3//gGFhDDTiuksgradgFN6yRayDP4SyZZa6ZMGHLIa17+M8A==", - "dev": true, - "requires": { - "node-gyp-build": "^4.2.0" - } - }, "utf8": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", @@ -22193,13 +20522,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/tasks/dev/3_uniswap_address_provider.ts b/tasks/dev/3_uniswap_address_provider.ts new file mode 100644 index 00000000..5898b4bb --- /dev/null +++ b/tasks/dev/3_uniswap_address_provider.ts @@ -0,0 +1,28 @@ +import { task } from 'hardhat/config'; +import { + deployLendingPoolAddressesProvider, + //deployLendingPoolAddressesProviderRegistry, +} from '../../helpers/contracts-deployments'; +import { getLendingPoolAddressesProviderRegistry } from '../../helpers/contracts-getters' +import { waitForTx } from '../../helpers/misc-utils'; +import { UniswapConfig } from '../../markets/uniswap'; + +task( + 'dev:deploy-uniswap-address-provider', + 'Deploy uniswap market address provider' +) + .addFlag('verify', 'Verify contracts at Etherscan') + .setAction(async ({ verify }, localBRE) => { + await localBRE.run('set-DRE'); + + const admin = await (await localBRE.ethers.getSigners())[0].getAddress(); + + const addressesProvider = await deployLendingPoolAddressesProvider(UniswapConfig.MarketId, verify); + await waitForTx(await addressesProvider.setPoolAdmin(admin)); + + const addressesProviderRegistry = await getLendingPoolAddressesProviderRegistry(); + await waitForTx( + await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 1) + ); + console.log(addressesProvider.address); + }); diff --git a/tasks/dev/3_lending_pool.ts b/tasks/dev/4_lending_pool.ts similarity index 100% rename from tasks/dev/3_lending_pool.ts rename to tasks/dev/4_lending_pool.ts diff --git a/tasks/dev/4_oracles.ts b/tasks/dev/5_oracles.ts similarity index 72% rename from tasks/dev/4_oracles.ts rename to tasks/dev/5_oracles.ts index 97f14c8a..d0d2cd08 100644 --- a/tasks/dev/4_oracles.ts +++ b/tasks/dev/5_oracles.ts @@ -24,57 +24,113 @@ task('dev:deploy-oracles', 'Deploy oracles for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({verify, pool}, localBRE) => { + await localBRE.run('set-DRE'); const poolConfig = loadPoolConfig(pool); + + console.log("Initialized pool config..."); + const { Mocks: {AllAssetsInitialPrices}, ProtocolGlobalParams: {UsdAddress, MockUsdPriceInWei}, LendingRateOracleRatesCommon, } = poolConfig as ICommonConfiguration; + console.log("Initialized mocks, global params and lending rate oracle rates"); + const defaultTokenList = { ...Object.fromEntries(Object.keys(TokenContractId).map((symbol) => [symbol, ''])), USD: UsdAddress, } as iAssetBase; + + console.log("Initialized defaultTokenList"); + const mockTokens = await getAllMockedTokens(); + + console.log("Initialized mock tokens"); + const mockTokensAddress = Object.keys(mockTokens).reduce>((prev, curr) => { prev[curr as keyof iAssetBase] = mockTokens[curr].address; return prev; }, defaultTokenList); + console.log(mockTokensAddress); + console.log("Initialized mock tokens addresses"); + const addressesProvider = await getLendingPoolAddressesProvider(); + + console.log("Got the addresses provider"); + const admin = await addressesProvider.getPoolAdmin(); + console.log("Got the admin"); + const fallbackOracle = await deployPriceOracle(verify); + + console.log("Deployed fallback price oracle"); + await waitForTx(await fallbackOracle.setEthUsdPrice(MockUsdPriceInWei)); + + console.log("set fallback ETH USD price"); + await setInitialAssetPricesInOracle(AllAssetsInitialPrices, mockTokensAddress, fallbackOracle); + console.log("Set initial asset prices in oracle"); + const mockAggregators = await deployAllMockAggregators(AllAssetsInitialPrices, verify); + console.log("Deployed mock aggregators"); + const allTokenAddresses = getAllTokenAddresses(mockTokens); + + console.log("Got all mock token addresses"); + const allAggregatorsAddresses = getAllAggregatorsAddresses(mockAggregators); + console.log("Got all aggregator addresses"); + const [tokens, aggregators] = getPairsTokenAggregator( allTokenAddresses, allAggregatorsAddresses ); + + console.log("Got \"pairsToken aggregator\""); await deployAaveOracle( [tokens, aggregators, fallbackOracle.address, await getWethAddress(poolConfig)], verify ); + + console.log("Deployed Aave oracle"); + await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address)); + console.log("Set price oracle in addresses provider"); + const lendingRateOracle = await deployLendingRateOracle(verify); + + console.log("Deployed lendingRateOracle"); + await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); + console.log("Set lending rate oracle in addresses provider"); + const {USD, ...tokensAddressesWithoutUsd} = allTokenAddresses; + + console.log("Initialized object with token addresses & usd") + const allReservesAddresses = { ...tokensAddressesWithoutUsd, }; + + console.log("Initialized object with all reserve addresses, allReservesAddresses:"); + console.log(allReservesAddresses); + await setInitialMarketRatesInRatesOracleByHelper( LendingRateOracleRatesCommon, allReservesAddresses, lendingRateOracle, admin ); - }); + + console.log("Task complete"); + }); \ No newline at end of file diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/6_initialize.ts similarity index 100% rename from tasks/dev/5_initialize.ts rename to tasks/dev/6_initialize.ts diff --git a/tasks/dev/6_wallet_balance_provider.ts b/tasks/dev/7_wallet_balance_provider.ts similarity index 100% rename from tasks/dev/6_wallet_balance_provider.ts rename to tasks/dev/7_wallet_balance_provider.ts diff --git a/tasks/migrations/aave.dev.ts b/tasks/migrations/aave.dev.ts index 1892cb53..e77e3e11 100644 --- a/tasks/migrations/aave.dev.ts +++ b/tasks/migrations/aave.dev.ts @@ -20,16 +20,22 @@ task('aave:dev', 'Deploy development enviroment') console.log('1. Deploy mock tokens'); await localBRE.run('dev:deploy-mock-tokens', {verify}); - console.log('2. Deploy address provider'); + console.log('2. Deploy Aave market address provider'); await localBRE.run('dev:deploy-address-provider', {verify}); + + console.log('3. Deploy Uniswap market address provider'); + await localBRE.run('dev:deploy-uniswap-address-provider', {verify}); - console.log('3. Deploy lending pool'); + console.log('4. Deploy Aave lending pool'); await localBRE.run('dev:deploy-lending-pool', {verify}); - console.log('4. Deploy oracles'); + console.log('5. Deploy oracles'); await localBRE.run('dev:deploy-oracles', {verify, pool: POOL_NAME}); - console.log('5. Initialize lending pool'); + console.log('6. Deploy Uniswap market oracles'); + await localBRE.run('dev:deploy-oracles', {verify, pool: "Uniswap"}); + + console.log('6. Initialize lending pool'); await localBRE.run('dev:initialize-lending-pool', {verify, pool: POOL_NAME}); console.log('\nFinished migration'); From 57986b76a881a821180f07392b194fac2049ef1c Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 25 Dec 2020 00:47:30 -0500 Subject: [PATCH 004/219] Testing --- helpers/configuration.ts | 7 +- helpers/contracts-deployments.ts | 1 + helpers/contracts-getters.ts | 4 +- helpers/contracts-helpers.ts | 4 +- helpers/init-helpers.ts | 13 +- helpers/oracles-helpers.ts | 1 + helpers/types.ts | 48 ++- helpers/uniswap-contracts-deployments.ts | 241 +++++++++++++ markets/aave/commons.ts | 9 +- markets/uniswap/commons.ts | 67 +--- markets/uniswap/index.ts | 14 +- package.json | 3 +- .../{4_lending_pool.ts => 3_lending_pool.ts} | 6 +- tasks/dev/3_uniswap_address_provider.ts | 28 -- tasks/dev/{5_oracles.ts => 4_oracles.ts} | 2 +- .../dev/{6_initialize.ts => 5_initialize.ts} | 2 + ...ovider.ts => 6_wallet_balance_provider.ts} | 0 tasks/dev/7_uniswap_market.ts | 322 ++++++++++++++++++ tasks/full/3_oracles.ts | 7 +- tasks/full/5_initialize.ts | 5 +- tasks/migrations/aave.dev.ts | 16 +- tasks/migrations/uniswap.mainnet.ts | 59 ++++ test/__setup.spec.ts | 10 +- test/test | 153 +++++++++ 24 files changed, 899 insertions(+), 123 deletions(-) create mode 100644 helpers/uniswap-contracts-deployments.ts rename tasks/dev/{4_lending_pool.ts => 3_lending_pool.ts} (92%) delete mode 100644 tasks/dev/3_uniswap_address_provider.ts rename tasks/dev/{5_oracles.ts => 4_oracles.ts} (97%) rename tasks/dev/{6_initialize.ts => 5_initialize.ts} (98%) rename tasks/dev/{7_wallet_balance_provider.ts => 6_wallet_balance_provider.ts} (100%) create mode 100644 tasks/dev/7_uniswap_market.ts create mode 100644 tasks/migrations/uniswap.mainnet.ts create mode 100644 test/test diff --git a/helpers/configuration.ts b/helpers/configuration.ts index 925f9365..13baa35a 100644 --- a/helpers/configuration.ts +++ b/helpers/configuration.ts @@ -25,10 +25,10 @@ export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => { switch (configName) { case ConfigNames.Aave: return AaveConfig; + case ConfigNames.Uniswap: + return UniswapConfig; case ConfigNames.Commons: return CommonsConfig; - case ConfigNames.Uniswap: - return UniswapConfig; default: throw new Error(`Unsupported pool configuration: ${Object.values(ConfigNames)}`); } @@ -44,6 +44,9 @@ export const getReservesConfigByPool = (pool: AavePools): iMultiPoolsAssets { [tokenSymbol, tokenSymbol, configData ? configData.reserveDecimals : decimals], verify ); + await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); console.log("deployAllMockTokens: deployed", tokenSymbol); } return tokens; diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index 22c1784b..34b0d134 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -153,7 +153,7 @@ export const getAllMockedTokens = async () => { const tokens: MockTokenMap = await Object.keys(TokenContractId).reduce>( async (acc, tokenSymbol) => { const accumulator = await acc; - console.log("getAllMockedTokens: got accumulator"); + console.log("getAllMockedTokens: got accumulator, next token:", tokenSymbol.toUpperCase()); const address = db.get(`${tokenSymbol.toUpperCase()}.${DRE.network.name}`).value().address; console.log("getAllMockedTokens: Initialized address for %s, address: %s", tokenSymbol, address); accumulator[tokenSymbol] = await getMintableERC20(address); @@ -177,6 +177,8 @@ export const getPairsTokenAggregator = ( const aggregatorAddressIndex = Object.keys(aggregatorsAddresses).findIndex( (value) => value === tokenSymbol ); + //console.log("getPairsTokenAggregator: tokenSymbol:", tokenSymbol); + //console.log("getPairsTokenAggregator: aggregatorsAddresses:\n\n", aggregatorsAddresses); const [, aggregatorAddress] = (Object.entries(aggregatorsAddresses) as [ string, tEthereumAddress diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 93f6bb30..df306c2a 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -157,10 +157,12 @@ export const getParamPerNetwork = ( } }; -export const getParamPerPool = ({ proto }: iParamsPerPool, pool: AavePools) => { +export const getParamPerPool = ({ proto, uniswap }: iParamsPerPool, pool: AavePools) => { switch (pool) { case AavePools.proto: return proto; + case AavePools.uniswap: + return uniswap; default: return proto; } diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index e80d2f91..96ec9df7 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -25,6 +25,7 @@ import { } from './contracts-deployments'; import { ZERO_ADDRESS } from './constants'; import { isZeroAddress } from 'ethereumjs-util'; +import { LendingPoolAddressesProvider } from '../types'; const chooseATokenDeployment = (id: eContractid) => { switch (id) { @@ -38,6 +39,7 @@ const chooseATokenDeployment = (id: eContractid) => { }; export const initReservesByHelper = async ( + addressProvider: LendingPoolAddressesProvider, reservesParams: iMultiPoolsAssets, tokenAddresses: { [symbol: string]: tEthereumAddress }, admin: tEthereumAddress, @@ -49,7 +51,7 @@ export const initReservesByHelper = async ( const stableAndVariableDeployer = await getStableAndVariableTokensHelper(); const atokenAndRatesDeployer = await getATokensAndRatesHelper(); - const addressProvider = await getLendingPoolAddressesProvider(); + //const addressProvider = await getLendingPoolAddressesProvider(); const poolAddress = await addressProvider.getLendingPool(); // Set aTokenAndRatesDeployer as temporal admin @@ -80,6 +82,7 @@ export const initReservesByHelper = async ( Object.entries(reservesParams).length * 4 } txs` ); + console.log("initReservesByHelper: tokenAddresses:", tokenAddresses); for (let reservesChunk of reservesChunks) { // Prepare data const tokens: string[] = []; @@ -95,13 +98,15 @@ export const initReservesByHelper = async ( const reservesDecimals: string[] = []; for (let [assetSymbol, { reserveDecimals }] of reservesChunk) { + console.log("initReservesByHelper: assetSymbol:\n%s", assetSymbol); const assetAddressIndex = Object.keys(tokenAddresses).findIndex( (value) => value === assetSymbol ); + console.log("initReservesByHelper: assetAddressIndex:\n%s", assetAddressIndex); const [, tokenAddress] = (Object.entries(tokenAddresses) as [string, string][])[ assetAddressIndex ]; - + console.log("initReservesByHelper: tokenAddress:\n%s", assetAddressIndex); const reserveParamIndex = Object.keys(reservesParams).findIndex( (value) => value === assetSymbol ); @@ -131,6 +136,7 @@ export const initReservesByHelper = async ( } // Deploy stable and variable deployers and save implementations + // PARAMS HANG IN LOCALHOST console.log("Hanging params:\ntokens:\n %s\n symbols:\n %s \n incentivesController: \n %s ", tokens, symbols, incentivesController); const tx1 = await waitForTx( await stableAndVariableDeployer.initDeployment(tokens, symbols, incentivesController) ); @@ -300,12 +306,13 @@ export const getPairsTokenAggregator = ( }; export const configureReservesByHelper = async ( + addressProvider: LendingPoolAddressesProvider, reservesParams: iMultiPoolsAssets, tokenAddresses: { [symbol: string]: tEthereumAddress }, helpers: AaveProtocolDataProvider, admin: tEthereumAddress ) => { - const addressProvider = await getLendingPoolAddressesProvider(); + //const addressProvider = await getLendingPoolAddressesProvider(); const atokenAndRatesDeployer = await getATokensAndRatesHelper(); const tokens: string[] = []; const symbols: string[] = []; diff --git a/helpers/oracles-helpers.ts b/helpers/oracles-helpers.ts index 242161e4..aaa19976 100644 --- a/helpers/oracles-helpers.ts +++ b/helpers/oracles-helpers.ts @@ -28,6 +28,7 @@ export const setInitialMarketRatesInRatesOracleByHelper = async ( string, IMarketRates ][]) { + console.log("Current asset symbol:", assetSymbol); const assetAddressIndex = Object.keys(assetsAddresses).findIndex( (value) => value === assetSymbol ); diff --git a/helpers/types.ts b/helpers/types.ts index 30c628e6..9c15dd13 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -22,36 +22,47 @@ export enum EthereumNetworkNames { export enum AavePools { proto = 'proto', + uniswap = 'uniswap', } export enum eContractid { Example = 'Example', LendingPoolAddressesProvider = 'LendingPoolAddressesProvider', + UniswapLendingPoolAddressesProvider = 'UniswapLendingPoolAddressesProvider', MintableERC20 = 'MintableERC20', MintableDelegationERC20 = 'MintableDelegationERC20', LendingPoolAddressesProviderRegistry = 'LendingPoolAddressesProviderRegistry', LendingPoolParametersProvider = 'LendingPoolParametersProvider', LendingPoolConfigurator = 'LendingPoolConfigurator', + UniswapLendingPoolConfigurator = 'UniswapLendingPoolConfigurator', ValidationLogic = 'ValidationLogic', ReserveLogic = 'ReserveLogic', GenericLogic = 'GenericLogic', LendingPool = 'LendingPool', + UniswapLendingPool = 'UniswapLendingPool', PriceOracle = 'PriceOracle', + UniswapPriceOracle = 'UniswapPriceOracle', Proxy = 'Proxy', MockAggregator = 'MockAggregator', LendingRateOracle = 'LendingRateOracle', + UniswapLendingRateOracle = 'UniswapLendingRateOracle', AaveOracle = 'AaveOracle', + UniswapAaveOracle = 'UniswapAaveOracle', DefaultReserveInterestRateStrategy = 'DefaultReserveInterestRateStrategy', LendingPoolCollateralManager = 'LendingPoolCollateralManager', + UniswapLendingPoolCollateralManager = 'UniswapLendingPoolCollateralManager', InitializableAdminUpgradeabilityProxy = 'InitializableAdminUpgradeabilityProxy', MockFlashLoanReceiver = 'MockFlashLoanReceiver', + UniswapMockFlashLoanReceiver = 'UniswapMockFlashLoanReceiver', WalletBalanceProvider = 'WalletBalanceProvider', + UniswapWalletBalanceProvider = 'UniswapWalletBalanceProvider', AToken = 'AToken', MockAToken = 'MockAToken', DelegationAwareAToken = 'DelegationAwareAToken', MockStableDebtToken = 'MockStableDebtToken', MockVariableDebtToken = 'MockVariableDebtToken', AaveProtocolDataProvider = 'AaveProtocolDataProvider', + UniswapAaveProtocolDataProvider = 'UniswapAaveProtocolDataProvider', IERC20Detailed = 'IERC20Detailed', StableDebtToken = 'StableDebtToken', VariableDebtToken = 'VariableDebtToken', @@ -61,12 +72,16 @@ export enum eContractid { ATokensAndRatesHelper = 'ATokensAndRatesHelper', UiPoolDataProvider = 'UiPoolDataProvider', WETHGateway = 'WETHGateway', + UniswapWETHGateway = 'UniswapWETHGateway', WETH = 'WETH', WETHMocked = 'WETHMocked', SelfdestructTransferMock = 'SelfdestructTransferMock', LendingPoolImpl = 'LendingPoolImpl', + UniswapLendingPoolImpl = 'UniswapLendingPoolImpl', LendingPoolConfiguratorImpl = 'LendingPoolConfiguratorImpl', + UniswapLendingPoolConfiguratorImpl = 'UniswapLendingPoolConfiguratorImpl', LendingPoolCollateralManagerImpl = 'LendingPoolCollateralManagerImpl', + UniswapLendingPoolCollateralManagerImpl = 'UniswapLendingPoolCollateralManagerImpl', } /* @@ -200,8 +215,13 @@ export interface iAssetBase { USD: T; REN: T; ENJ: T; - WETHDAI: T; - WETHWBTC: T; + UNI_WETH: T; + UNI_WBTC: T; + UNI_DAI: T; + UNI_USDC: T; + UNI_USDT: T; + UNI_WETHDAI: T; + UNI_WETHWBTC: T; } export type iAssetsWithoutETH = Omit, 'ETH'>; @@ -234,13 +254,13 @@ export type iAavePoolAssets = Pick< export type iUniswapPoolAssets = Pick< iAssetsWithoutUSD, - | 'DAI' - | 'USDC' - | 'USDT' - | 'WBTC' - | 'WETH' - | 'WETHDAI' - | 'WETHWBTC' + | 'UNI_DAI' + | 'UNI_USDC' + | 'UNI_USDT' + | 'UNI_WBTC' + | 'UNI_WETH' + | 'UNI_WETHDAI' + | 'UNI_WETHWBTC' >; export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; @@ -271,8 +291,13 @@ export enum TokenContractId { YFI = 'YFI', UNI = 'UNI', ENJ = 'ENJ', - WETHDAI = 'WETHDAI', - WETHWBTC = 'WETHWBTC', + UNI_WETH = 'WETH', + UNI_WBTC = 'WBTC', + UNI_DAI = 'DAI', + UNI_USDC = 'USDC', + UNI_USDT = 'USDT', + UNI_WETHDAI = 'WETHDAI', + UNI_WETHWBTC = 'WETHWBTC', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { @@ -313,6 +338,7 @@ export interface iParamsPerNetwork { export interface iParamsPerPool { [AavePools.proto]: T; + [AavePools.uniswap]: T; } export interface iBasicDistributionParams { diff --git a/helpers/uniswap-contracts-deployments.ts b/helpers/uniswap-contracts-deployments.ts new file mode 100644 index 00000000..0c28b324 --- /dev/null +++ b/helpers/uniswap-contracts-deployments.ts @@ -0,0 +1,241 @@ +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 + ); diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index fecd714f..e059c961 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -23,8 +23,13 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), - WETHDAI: oneEther.multipliedBy('22.407436').toFixed(), - WETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), + UNI_WETH:oneEther.toFixed(), + UNI_WBTC: oneEther.multipliedBy('47.332685').toFixed(), + UNI_DAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + UNI_USDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + UNI_USDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + UNI_WETHDAI: oneEther.multipliedBy('22.407436').toFixed(), + UNI_WETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; // ---------------- diff --git a/markets/uniswap/commons.ts b/markets/uniswap/commons.ts index 939b32ee..c12b4570 100644 --- a/markets/uniswap/commons.ts +++ b/markets/uniswap/commons.ts @@ -23,8 +23,13 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), - WETHDAI: oneEther.multipliedBy('22.407436').toFixed(), - WETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), + UNI_WETH:oneEther.toFixed(), + UNI_WBTC: oneEther.multipliedBy('47.332685').toFixed(), + UNI_DAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + UNI_USDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + UNI_USDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + UNI_WETHDAI: oneEther.multipliedBy('22.407436').toFixed(), + UNI_WETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; // ---------------- @@ -54,67 +59,25 @@ export const CommonsConfig: ICommonConfiguration = { }, // TODO: reorg alphabetically, checking the reason of tests failing LendingRateOracleRatesCommon: { - WETH: { + UNI_WETH: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - DAI: { + UNI_DAI: { borrowRate: oneRay.multipliedBy(0.039).toFixed(), }, - TUSD: { - borrowRate: oneRay.multipliedBy(0.035).toFixed(), - }, - USDC: { + UNI_USDC: { borrowRate: oneRay.multipliedBy(0.039).toFixed(), }, - SUSD: { + UNI_USDT: { borrowRate: oneRay.multipliedBy(0.035).toFixed(), }, - USDT: { - borrowRate: oneRay.multipliedBy(0.035).toFixed(), - }, - BAT: { + UNI_WBTC: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - AAVE: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - LINK: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - KNC: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - MKR: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - MANA: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - WBTC: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - ZRX: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - SNX: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - YFI: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - REN: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - UNI: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - BUSD: { + UNI_WETHDAI: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - WETHDAI: { - borrowRate: oneRay.multipliedBy(0.05).toFixed(), - }, - WETHWBTC: { + UNI_WETHWBTC: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, }, @@ -267,6 +230,8 @@ export const CommonsConfig: ICommonConfiguration = { YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4', ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + WETHDAI: ZERO_ADDRESS, + WETHWBTC: ZERO_ADDRESS, }, [EthereumNetwork.tenderlyMain]: { AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', diff --git a/markets/uniswap/index.ts b/markets/uniswap/index.ts index 37daa4af..d92518df 100644 --- a/markets/uniswap/index.ts +++ b/markets/uniswap/index.ts @@ -21,13 +21,13 @@ export const UniswapConfig: IUniswapConfiguration = { MarketId: 'Uniswap V2 market', ProviderId: 2, ReservesConfig: { - DAI: strategyDAI, - USDC: strategyUSDC, - USDT: strategyUSDT, - WBTC: strategyWBTC, - WETH: strategyWETH, - WETHDAI: strategyWETHDAI, - WETHWBTC: strategyWETHWBTC + UNI_DAI: strategyDAI, + UNI_USDC: strategyUSDC, + UNI_USDT: strategyUSDT, + UNI_WBTC: strategyWBTC, + UNI_WETH: strategyWETH, + UNI_WETHDAI: strategyWETHDAI, + UNI_WETHWBTC: strategyWETHWBTC }, ReserveAssets: { [eEthereumNetwork.buidlerevm]: {}, diff --git a/package.json b/package.json index d3c73712..cd9c9e3e 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ "aave:kovan:full:initialize": "npm run hardhat:kovan -- full:initialize-lending-pool --verify --pool Aave", "aave:ropsten:full:migration": "npm run compile && npm run hardhat:ropsten -- aave:mainnet --verify", "aave:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- aave:mainnet", - "aave:fork:main": "npm run compile && MAINNET_FORK=true hardhat aave:mainnet", + "aave:fork:main": "npm run compile && MAINNET_FORK=true hardhat aave:mainnet", + "uniswap:fork:main": "npm run compile && MAINNET_FORK=true hardhat uniswap:mainnet", "aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify", "aave:main:full:initialize": "npm run compile && MAINNET_FORK=true full:initialize-tokens --pool Aave", "dev:prettier": "prettier --write .", diff --git a/tasks/dev/4_lending_pool.ts b/tasks/dev/3_lending_pool.ts similarity index 92% rename from tasks/dev/4_lending_pool.ts rename to tasks/dev/3_lending_pool.ts index b1aeb58c..692c8386 100644 --- a/tasks/dev/4_lending_pool.ts +++ b/tasks/dev/3_lending_pool.ts @@ -18,15 +18,17 @@ task('dev:deploy-lending-pool', 'Deploy lending pool for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') .setAction(async ({verify}, localBRE) => { await localBRE.run('set-DRE'); - + // TEST--- CURRENTLY FAILS BECAUSE ALREADY HAS AN IMPLEMENTATION, SHOULD BE DONE BEFORE UNI MARKET TASK const addressesProvider = await getLendingPoolAddressesProvider(); - + const lendingPoolImpl = await deployLendingPool(verify); // Set lending pool impl to Address Provider await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address)); const address = await addressesProvider.getLendingPool(); + console.log("AAVE MARKET LENDING POOL:", address); + const lendingPoolProxy = await getLendingPool(address); await insertContractAddressInDb(eContractid.LendingPool, lendingPoolProxy.address); diff --git a/tasks/dev/3_uniswap_address_provider.ts b/tasks/dev/3_uniswap_address_provider.ts deleted file mode 100644 index 5898b4bb..00000000 --- a/tasks/dev/3_uniswap_address_provider.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { task } from 'hardhat/config'; -import { - deployLendingPoolAddressesProvider, - //deployLendingPoolAddressesProviderRegistry, -} from '../../helpers/contracts-deployments'; -import { getLendingPoolAddressesProviderRegistry } from '../../helpers/contracts-getters' -import { waitForTx } from '../../helpers/misc-utils'; -import { UniswapConfig } from '../../markets/uniswap'; - -task( - 'dev:deploy-uniswap-address-provider', - 'Deploy uniswap market address provider' -) - .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({ verify }, localBRE) => { - await localBRE.run('set-DRE'); - - const admin = await (await localBRE.ethers.getSigners())[0].getAddress(); - - const addressesProvider = await deployLendingPoolAddressesProvider(UniswapConfig.MarketId, verify); - await waitForTx(await addressesProvider.setPoolAdmin(admin)); - - const addressesProviderRegistry = await getLendingPoolAddressesProviderRegistry(); - await waitForTx( - await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 1) - ); - console.log(addressesProvider.address); - }); diff --git a/tasks/dev/5_oracles.ts b/tasks/dev/4_oracles.ts similarity index 97% rename from tasks/dev/5_oracles.ts rename to tasks/dev/4_oracles.ts index d0d2cd08..b8c29660 100644 --- a/tasks/dev/5_oracles.ts +++ b/tasks/dev/4_oracles.ts @@ -58,7 +58,7 @@ task('dev:deploy-oracles', 'Deploy oracles for dev enviroment') const addressesProvider = await getLendingPoolAddressesProvider(); - console.log("Got the addresses provider"); + console.log("Got the addresses provider (check if different both times):", addressesProvider.address); const admin = await addressesProvider.getPoolAdmin(); diff --git a/tasks/dev/6_initialize.ts b/tasks/dev/5_initialize.ts similarity index 98% rename from tasks/dev/6_initialize.ts rename to tasks/dev/5_initialize.ts index c62f31ce..9a3896a5 100644 --- a/tasks/dev/6_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -53,6 +53,7 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') const treasuryAddress = await getTreasuryAddress(poolConfig); await initReservesByHelper( + addressesProvider, reservesParams, protoPoolReservesAddresses, admin, @@ -61,6 +62,7 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') verify ); await configureReservesByHelper( + addressesProvider, reservesParams, protoPoolReservesAddresses, testHelpers, diff --git a/tasks/dev/7_wallet_balance_provider.ts b/tasks/dev/6_wallet_balance_provider.ts similarity index 100% rename from tasks/dev/7_wallet_balance_provider.ts rename to tasks/dev/6_wallet_balance_provider.ts diff --git a/tasks/dev/7_uniswap_market.ts b/tasks/dev/7_uniswap_market.ts new file mode 100644 index 00000000..aa73fc40 --- /dev/null +++ b/tasks/dev/7_uniswap_market.ts @@ -0,0 +1,322 @@ +import { task } from 'hardhat/config'; +import { + deployATokensAndRatesHelper, + deployStableAndVariableTokensHelper, + deployAaveProtocolDataProvider, + deployLendingPoolAddressesProvider, //Test +} from '../../helpers/contracts-deployments'; +import { + deployUniswapLendingPoolAddressesProvider, + deployUniswapLendingPool, + deployUniswapLendingPoolConfigurator, + deployUniswapPriceOracle, + deployUniswapAaveOracle, + deployUniswapLendingRateOracle, + deployUniswapLendingPoolCollateralManager, + deployUniswapMockFlashLoanReceiver, + deployUniswapWETHGateway, + deployUniswapWalletBalancerProvider, +} from '../../helpers/uniswap-contracts-deployments'; +import { tEthereumAddress, + eContractid, + AavePools, + ICommonConfiguration, + iAssetBase, + TokenContractId, + IMarketRates, +} from '../../helpers/types'; +import { + getLendingPoolAddressesProviderRegistry, + getLendingPoolAddressesProvider, //Test + getLendingPool, + getLendingPoolConfiguratorProxy, + getAllMockedTokens, + getPairsTokenAggregator, +} from '../../helpers/contracts-getters'; +import { waitForTx, filterMapBy } from '../../helpers/misc-utils'; +import { UniswapConfig } from '../../markets/uniswap'; +import { insertContractAddressInDb } from '../../helpers/contracts-helpers'; +import { + setInitialAssetPricesInOracle, + deployAllMockAggregators, + setInitialMarketRatesInRatesOracleByHelper, +} from '../../helpers/oracles-helpers'; +import {getAllAggregatorsAddresses, getAllTokenAddresses} from '../../helpers/mock-helpers'; +import { + ConfigNames, + getReservesConfigByPool, + getTreasuryAddress, + loadPoolConfig, + getWethAddress, +} from '../../helpers/configuration'; +import { + configureReservesByHelper, + initReservesByHelper, +} from '../../helpers/init-helpers'; +import { ZERO_ADDRESS } from '../../helpers/constants'; + + +const pool = ConfigNames.Uniswap; +/** + * @dev addressesProvider is actually created here, so we don't need to use getAddressesProvider + */ +task( + 'dev:deploy-uniswap-market', + 'Deploy uniswap market' +) + .addFlag('verify', 'Verify contracts at Etherscan') + .setAction(async ({ verify }, localBRE) => { + await localBRE.run('set-DRE'); + + const admin = await (await localBRE.ethers.getSigners())[0].getAddress(); + + const testProvider = await getLendingPoolAddressesProvider(); + console.log("Addresses provider from function (pre re-deploy):", testProvider.address); + const addressesProvider = await deployLendingPoolAddressesProvider(UniswapConfig.MarketId, verify); + console.log("Addresses provider in execution::", addressesProvider.address) + + const testProviderPost = await getLendingPoolAddressesProvider(); + console.log("Addresses provider from function (pre re-deploy):", testProviderPost.address); + console.log("Addresses provider from function (post re-deploy) should be different:") + await waitForTx(await addressesProvider.setPoolAdmin(admin)); + + + const addressesProviderRegistry = await getLendingPoolAddressesProviderRegistry(); + await waitForTx( + await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 1) + ); + console.log(addressesProvider.address); + + + /** + * LENDING POOL DEPLOYMENT + */ + const lendingPoolImpl = await deployUniswapLendingPool(verify); + + await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address)); + + const address = await addressesProvider.getLendingPool(); + console.log("UNISWAP MARKET LENDING POOL:", address); + const lendingPoolProxy = await getLendingPool(address); + await insertContractAddressInDb(eContractid.UniswapLendingPool, lendingPoolProxy.address); + + const lendingPoolConfiguratorImpl = await deployUniswapLendingPoolConfigurator(verify); + + // Set lending pool conf impl to Address Provider + await waitForTx( + await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImpl.address) + ); + + const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy( + await addressesProvider.getLendingPoolConfigurator() + ); + + await insertContractAddressInDb( + eContractid.UniswapLendingPoolConfigurator, + lendingPoolConfiguratorProxy.address + ); + + // Deploy deployment helpers + await deployStableAndVariableTokensHelper( + [lendingPoolProxy.address, addressesProvider.address], + verify + ); + await deployATokensAndRatesHelper( + [lendingPoolProxy.address, addressesProvider.address, lendingPoolConfiguratorProxy.address], + verify + ); + + /** + * @dev Oracle deployment section + */ + + console.log("Uniswap oracle deployment beginning.") + const poolConfig = loadPoolConfig(pool); + console.log("Initialized pool config..."); + + const { + Mocks: {AllAssetsInitialPrices}, + ProtocolGlobalParams: {UsdAddress, MockUsdPriceInWei}, + LendingRateOracleRatesCommon, + } = poolConfig as ICommonConfiguration; + console.log("Initialized mocks, global params and lending rate oracle rates"); + + const defaultTokenList = { + ...Object.fromEntries(Object.keys(TokenContractId).map((symbol) => [symbol, ''])), + USD: UsdAddress, + } as iAssetBase; + + console.log("Initialized defaultTokenList"); + + const mockTokens = await getAllMockedTokens(); + + console.log("Initialized mock tokens"); + + const mockTokensAddress = Object.keys(mockTokens).reduce>((prev, curr) => { + prev[curr as keyof iAssetBase] = mockTokens[curr].address; + return prev; + }, defaultTokenList); + console.log(mockTokensAddress); + console.log("Initialized mock tokens addresses"); + + // No need to re-initialize addressesProvider and admin + + const fallbackOracle = await deployUniswapPriceOracle(verify); + console.log("Deployed fallback price oracle"); + + await waitForTx(await fallbackOracle.setEthUsdPrice(MockUsdPriceInWei)); + console.log("set fallback ETH USD price"); + + await setInitialAssetPricesInOracle(AllAssetsInitialPrices, mockTokensAddress, fallbackOracle); + console.log("Set initial asset prices in oracle"); + + const mockAggregators = await deployAllMockAggregators(AllAssetsInitialPrices, verify); + console.log("Deployed mock aggregators"); + + const allTokenAddresses = getAllTokenAddresses(mockTokens); + console.log("Got all mock token addresses"); + + const allAggregatorsAddresses = getAllAggregatorsAddresses(mockAggregators); + console.log("Got all aggregator addresses"); + console.log("allTokenAddresses object: \n", allTokenAddresses); + //Should modify this to potentially contain only the tokens in the Uniswap market + // const [tokens, aggregators] = getPairsTokenAggregator( + // allTokenAddresses, + // allAggregatorsAddresses + // ); + // console.log("Got \"pairsToken aggregator\""); + // console.log("Tokens: \n", tokens); + + // const assetAddressIndex = Object.keys(allReservesAddresses).findIndex( + // (value) => value === assetSymbol + // ); + // const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[ + // assetAddressIndex + // ]; + // assetAddresses.push(assetAddress); + + // await deployUniswapAaveOracle( + // [tokens, aggregators, fallbackOracle.address, await getWethAddress(poolConfig)], + // verify + // ); + console.log("Deployed Uniswap Aave oracle"); + + await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address)); + console.log("Set price oracle in addresses provider"); + + const lendingRateOracle = await deployUniswapLendingRateOracle(verify); + console.log("Deployed lendingRateOracle"); + + await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); + console.log("Set lending rate oracle in addresses provider"); + + const {USD, ...tokensAddressesWithoutUsd} = allTokenAddresses; + console.log("Initialized object with token addresses & usd") + + const allReservesAddresses = { + ...tokensAddressesWithoutUsd, + }; + console.log("Initialized object with all reserve addresses, allReservesAddresses:"); + console.log(allReservesAddresses); + + console.log("LendingRateOracleRatesCommon: \n", LendingRateOracleRatesCommon); + // + // -- test + // + const [tokens, aggregators] = getPairsTokenAggregator( + allTokenAddresses, + allAggregatorsAddresses + ); + console.log("Got \"pairsToken aggregator\""); + console.log("Tokens: \n", tokens); + const assetAddresses: string[] = []; + const aggregatorAddresses: string[] = []; + for (const [assetSymbol, {borrowRate}] of Object.entries(LendingRateOracleRatesCommon) as [ + string, + IMarketRates + ][]) { + const assetAddressIndex = Object.keys(allReservesAddresses).findIndex( + (value) => value === assetSymbol + ); + const [, assetAddress] = (Object.entries(allReservesAddresses) as [string, string][])[ + assetAddressIndex + ]; + + const [, aggregatorAddress] = (Object.entries(allAggregatorsAddresses) as [string, string][])[ + assetAddressIndex + ]; + aggregatorAddresses.push(aggregatorAddress); + assetAddresses.push(assetAddress); + } + console.log("\nPRICE ORACLE PARAMS:\nassetAddresses: %s\naggregatorAddresses: %s", assetAddresses, aggregatorAddresses); + await deployUniswapAaveOracle( + [assetAddresses, aggregatorAddresses, fallbackOracle.address, await getWethAddress(poolConfig)], + verify + ); + // + // -- test end + // + console.log("TEST END-----------------------------------------------------------------------"); + await setInitialMarketRatesInRatesOracleByHelper( + LendingRateOracleRatesCommon, + allReservesAddresses, + lendingRateOracle, + admin + ); + + console.log("Task complete"); + + /** + * @dev Initialization + */ + + // No need to initialize poolConfig, mockTokens, allTokenAddresses, admin and + // addressesProvider and protoReservesAddresses (we use allReserveAddresses) + + const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address, verify); + + const reservesParams = getReservesConfigByPool(AavePools.uniswap); + + const treasuryAddress = await getTreasuryAddress(poolConfig); + + await initReservesByHelper( + addressesProvider, + reservesParams, + allReservesAddresses, + admin, + treasuryAddress, + ZERO_ADDRESS, + verify + ); + + await configureReservesByHelper( + addressesProvider, + reservesParams, + allReservesAddresses, + testHelpers, + admin + ); + + const collateralManager = await deployUniswapLendingPoolCollateralManager(verify); + await waitForTx( + await addressesProvider.setLendingPoolCollateralManager(collateralManager.address) + ); + + const mockFlashLoanReceiver = await deployUniswapMockFlashLoanReceiver( + addressesProvider.address, + verify + ); + + await insertContractAddressInDb( + eContractid.UniswapMockFlashLoanReceiver, + mockFlashLoanReceiver.address + ); + + await deployUniswapWalletBalancerProvider(verify); + + await insertContractAddressInDb(eContractid.AaveProtocolDataProvider, testHelpers.address); + + const lendingPoolAddress = await addressesProvider.getLendingPool(); + const wethAddress = await getWethAddress(poolConfig); + await deployUniswapWETHGateway([wethAddress, lendingPoolAddress]); + }); diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index b064328f..093ea43c 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -1,5 +1,5 @@ import { task } from 'hardhat/config'; -import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { getParamPerNetwork, getParamPerPool } from '../../helpers/contracts-helpers'; import { deployAaveOracle, deployLendingRateOracle } from '../../helpers/contracts-deployments'; import { setInitialMarketRatesInRatesOracleByHelper } from '../../helpers/oracles-helpers'; import { ICommonConfiguration, eEthereumNetwork, SymbolMap } from '../../helpers/types'; @@ -32,6 +32,8 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') FallbackOracle, ChainlinkAggregator, } = poolConfig as ICommonConfiguration; + + //console.log("------------------------------------------------ReserveAssets:\n", ReserveAssets); const lendingRateOracles = getLendingRateOracles(poolConfig); const addressesProvider = await getLendingPoolAddressesProvider(); const admin = await getGenesisPoolAdmin(poolConfig); @@ -40,13 +42,14 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') const fallbackOracleAddress = await getParamPerNetwork(FallbackOracle, network); const reserveAssets = await getParamPerNetwork(ReserveAssets, network); const chainlinkAggregators = await getParamPerNetwork(ChainlinkAggregator, network); + //console.log("------------------------------------------------reserveAssets:\n", reserveAssets); const tokensToWatch: SymbolMap = { ...reserveAssets, USD: UsdAddress, }; const [tokens, aggregators] = getPairsTokenAggregator(tokensToWatch, chainlinkAggregators); - + console.log("tokens:\n %s \n aggregators: \n %s", tokens, aggregators); const aaveOracle = notFalsyOrZeroAddress(aaveOracleAddress) ? await getAaveOracle(aaveOracleAddress) : await deployAaveOracle( diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 444f55d8..77672bdc 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -36,6 +36,7 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const testHelpers = await getAaveProtocolDataProvider(); + console.log("reserveAssets:\n", reserveAssets); const admin = await addressesProvider.getPoolAdmin(); if (!reserveAssets) { throw 'Reserve assets is undefined. Check ReserveAssets configuration at config directory'; @@ -43,8 +44,8 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const treasuryAddress = await getTreasuryAddress(poolConfig); - await initReservesByHelper(ReservesConfig, reserveAssets, admin, treasuryAddress, ZERO_ADDRESS, verify); - await configureReservesByHelper(ReservesConfig, reserveAssets, testHelpers, admin); + await initReservesByHelper(addressesProvider, ReservesConfig, reserveAssets, admin, treasuryAddress, ZERO_ADDRESS, verify); + await configureReservesByHelper(addressesProvider, ReservesConfig, reserveAssets, testHelpers, admin); const collateralManager = await deployLendingPoolCollateralManager(verify); await waitForTx( diff --git a/tasks/migrations/aave.dev.ts b/tasks/migrations/aave.dev.ts index e77e3e11..e92d894d 100644 --- a/tasks/migrations/aave.dev.ts +++ b/tasks/migrations/aave.dev.ts @@ -22,22 +22,22 @@ task('aave:dev', 'Deploy development enviroment') console.log('2. Deploy Aave market address provider'); await localBRE.run('dev:deploy-address-provider', {verify}); - - console.log('3. Deploy Uniswap market address provider'); - await localBRE.run('dev:deploy-uniswap-address-provider', {verify}); - console.log('4. Deploy Aave lending pool'); + console.log('3. Deploy Aave lending pool'); await localBRE.run('dev:deploy-lending-pool', {verify}); - console.log('5. Deploy oracles'); + console.log('4. Deploy oracles'); await localBRE.run('dev:deploy-oracles', {verify, pool: POOL_NAME}); - console.log('6. Deploy Uniswap market oracles'); - await localBRE.run('dev:deploy-oracles', {verify, pool: "Uniswap"}); + // console.log('6. Deploy Uniswap market oracles'); + // await localBRE.run('dev:deploy-oracles', {verify, pool: "Uniswap"}); - console.log('6. Initialize lending pool'); + console.log('5. Initialize lending pool'); await localBRE.run('dev:initialize-lending-pool', {verify, pool: POOL_NAME}); + console.log('6. Deploy Uniswap market'); + await localBRE.run('dev:deploy-uniswap-market', {verify}); + console.log('\nFinished migration'); printContracts(); }); diff --git a/tasks/migrations/uniswap.mainnet.ts b/tasks/migrations/uniswap.mainnet.ts new file mode 100644 index 00000000..7945dca6 --- /dev/null +++ b/tasks/migrations/uniswap.mainnet.ts @@ -0,0 +1,59 @@ +import {task} from 'hardhat/config'; +import {ExternalProvider} from '@ethersproject/providers'; +import {checkVerification} from '../../helpers/etherscan-verification'; +import {ConfigNames} from '../../helpers/configuration'; +import {EthereumNetworkNames} from '../../helpers/types'; +import {printContracts} from '../../helpers/misc-utils'; + +task('uniswap:mainnet', 'Deploy development enviroment') + .addFlag('verify', 'Verify contracts at Etherscan') + .setAction(async ({verify}, DRE) => { + const POOL_NAME = ConfigNames.Uniswap; + const network = DRE.network.name; + await DRE.run('set-DRE'); + + // Prevent loss of gas verifying all the needed ENVs for Etherscan verification + if (verify) { + checkVerification(); + } + + if (network.includes('tenderly')) { + console.log('- Setting up Tenderly provider'); + await DRE.tenderlyRPC.initializeFork(); + const provider = new DRE.ethers.providers.Web3Provider(DRE.tenderlyRPC as any); + DRE.ethers.provider = provider; + } + + console.log('Migration started\n'); + + console.log('1. Deploy address provider'); + await DRE.run('full:deploy-address-provider', {pool: POOL_NAME}); + + console.log('2. Deploy lending pool'); + await DRE.run('full:deploy-lending-pool'); + + 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. Initialize lending pool'); + await DRE.run('full:initialize-lending-pool', {pool: POOL_NAME}); + + if (verify) { + printContracts(); + console.log('4. Veryfing contracts'); + await DRE.run('verify:general', {all: true, pool: POOL_NAME}); + + console.log('5. Veryfing aTokens and debtTokens'); + await DRE.run('verify:tokens', {pool: POOL_NAME}); + } + + if (network.includes('tenderly')) { + const postDeployHead = DRE.tenderlyRPC.getHead(); + console.log('Tenderly UUID', postDeployHead); + } + console.log('\nFinished migrations'); + printContracts(); + }); diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index 45479bb7..51542de9 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -159,6 +159,13 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { REN: mockTokens.REN.address, UNI: mockTokens.UNI.address, ENJ: mockTokens.ENJ.address, + UNI_WETH: mockTokens.WETH.address, + UNI_WBTC: mockTokens.WBTC.address, + UNI_DAI: mockTokens.DAI.address, + UNI_USDC: mockTokens.USDC.address, + UNI_USDT: mockTokens.USDT.address, + UNI_WETHDAI: mockTokens.UNI_WETHDAI.address, + UNI_WETHWBTC: mockTokens.UNI_WETHWBTC.address, USD: USD_ADDRESS, }, fallbackOracle @@ -213,8 +220,9 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const treasuryAddress = await getTreasuryAddress(config); - await initReservesByHelper(reservesParams, allReservesAddresses, admin, treasuryAddress, ZERO_ADDRESS, false); + await initReservesByHelper(addressesProvider, reservesParams, allReservesAddresses, admin, treasuryAddress, ZERO_ADDRESS, false); await configureReservesByHelper( + addressesProvider, reservesParams, allReservesAddresses, testHelpers, diff --git a/test/test b/test/test new file mode 100644 index 00000000..6b201f6c --- /dev/null +++ b/test/test @@ -0,0 +1,153 @@ +N# Contracts: 152 +MintableERC20: 0xB00cC45B4a7d3e1FEE684cFc4417998A1c183e6d +LendingPoolAddressesProvider: 0x0459c841b02Aee8730730C737582c53B20a27288 +LendingPoolAddressesProviderRegistry: 0x22474D350EC2dA53D717E30b96e9a2B7628Ede5b +ReserveLogic: 0x7fAeC7791277Ff512c41CA903c177B2Ed952dDAc +GenericLogic: 0x33958cC3535Fc328369EAC2B2Bebd120D67C7fa1 +ValidationLogic: 0x2cBbbBE1B75Ad7848F0844215816F551f429c64f +LendingPoolImpl: 0x8456161947DFc1fC159A0B26c025cD2b4bba0c3e +LendingPool: 0xbAc762e2000b6815268587b081Fd17aC25519aD5 +LendingPoolConfiguratorImpl: 0x5F6CaC05CDF893f029b29F44d368eAeD40e573B6 +LendingPoolConfigurator: 0x2C4603396dE2F08642354A3A102760827FfFe113 +StableAndVariableTokensHelper: 0xadcD6f616fCEEbEd731B2B3F01B8bd51A08b5CbD +ATokensAndRatesHelper: 0x603A373A1571783bD82b708C20a5A4b019BAB78F +DAI: 0x7c2C195CD6D34B8F845992d380aADB2730bB9C6F +AAVE: 0x8858eeB3DfffA017D4BCE9801D340D36Cf895CCf +TUSD: 0x0078371BDeDE8aAc7DeBfFf451B74c5EDB385Af7 +BAT: 0xf4e77E5Da47AC3125140c470c71cBca77B5c638c +WETHMocked: 0x09d728F76D543DB1925f7d1Fd8823e4e82700F99 +WETH: 0xf784709d2317D872237C4bC22f867d1BAe2913AB +USDC: 0x3619DbE27d7c1e7E91aA738697Ae7Bc5FC3eACA5 +USDT: 0x038B86d9d8FAFdd0a02ebd1A476432877b0107C8 +SUSD: 0x1A1FEe7EeD918BD762173e4dc5EfDB8a78C924A8 +ZRX: 0x500D1d6A4c7D8Ae28240b47c8FCde034D827fD5e +MKR: 0xc4905364b78a742ccce7B890A89514061E47068D +WBTC: 0xD6C850aeBFDC46D7F4c207e445cC0d6B0919BDBe +LINK: 0x8B5B7a6055E54a36fF574bbE40cf2eA68d5554b3 +KNC: 0xEcc0a6dbC0bb4D51E4F84A315a9e5B0438cAD4f0 +MANA: 0x20Ce94F404343aD2752A2D01b43fa407db9E0D00 +REN: 0x1d80315fac6aBd3EfeEbE97dEc44461ba7556160 +SNX: 0x2D8553F9ddA85A9B3259F6Bf26911364B85556F5 +BUSD: 0x52d3b94181f8654db2530b0fEe1B19173f519C52 +USD: 0xd15468525c35BDBC1eD8F2e09A00F8a173437f2f +YFI: 0x7e35Eaf7e8FBd7887ad538D4A38Df5BbD073814a +UNI: 0x5bcb88A0d20426e451332eE6C4324b0e663c50E0 +ENJ: 0x3521eF8AaB0323004A6dD8b03CE890F4Ea3A13f5 +WETHDAI: 0x53369fd4680FfE3DfF39Fc6DDa9CfbfD43daeA2E +WETHWBTC: 0xB00cC45B4a7d3e1FEE684cFc4417998A1c183e6d +PriceOracle: 0x06bA8d8af0dF898D0712DffFb0f862cC51AF45c2 +MockAggregator: 0xA0AB1cB92A4AF81f84dCd258155B5c25D247b54E +AaveOracle: 0xD662fb7FDC7526C79AA4417d2A4415416e057ec4 +LendingRateOracle: 0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89 +AaveProtocolDataProvider: 0xf45C720549136d5E2d6a5A2F12573A36E36C3411 +stableDebtAAVE: 0xe3C388495669b8624753a275675AEf9eCc8Eaaa4 +variableDebtAAVE: 0xbdA8106CA657E2bfe1a125f0D0DDE47bA85E92c8 +stableDebtBAT: 0xa8c48Fad16b34bc9BC1203f1784D36CDf61dfD9c +variableDebtBAT: 0x5A7dE46c8176AF8550Df2fEF14464c2cB3B0EE5e +aAAVE: 0x1433d6d0794262c09f19E64177c0dD69A0e4D648 +strategyAAVE: 0x329e6747250B326E5E8029154DFFfE93F4f27016 +aBAT: 0x1A2e1C9d403E9DD6Da5022a14590ec875fBb75ba +strategyBAT: 0x12d5da143C6f7d3322C9b32cdF3a6Cae390A5293 +stableDebtBUSD: 0x453697f5d829556a0373F2b835cF94242B078C9e +variableDebtBUSD: 0x03D049FCA4dE1DA80F9DDF4bf0008115c74C0Da2 +stableDebtDAI: 0x30dDD022BC4df9BB0e6ce94A5535F2137dEA3755 +variableDebtDAI: 0xbfC8B61A3e6eD07C092a74603CeCAe91254745D6 +aBUSD: 0x1BC353ae7758eff98129928631a2D17d69BAb5FA +strategyBUSD: 0x270176D7DB4ec8d2a16b90C78B424AAdbBcFE298 +aDAI: 0x6A61442dBCF10E7168FfcD850CDf7c91Cad3E666 +strategyDAI: 0xA9DD0c06755734f4327F405cd20897D79FaCcFAE +stableDebtENJ: 0x6C0A2d54B37d8Cd321a25328753077D43A387303 +variableDebtENJ: 0x1372E5e41E22BaB997aD453469F0DFB9569dB121 +stableDebtKNC: 0x9bF0208c881906fAC92112320425b403e08Fe44b +variableDebtKNC: 0x6028834D13a4eec68b289E125222e5e5e86a5503 +aENJ: 0x2108E7A4B53516883b60a40ae02600697c8065A2 +strategyENJ: 0x64980e3e653Fe43813A41b9C5AcDB394d7A7320F +aKNC: 0x0f22acabf1Aa485565693B671Fc68B0583f8FEB0 +strategyKNC: 0xC45DA1E746911C76E51CA28b8d8A876735797E3C +stableDebtLINK: 0x3E650a21eAACE6314E98569E8A37FDA1d4cfBE28 +variableDebtLINK: 0xA7430bFB0f7332B1456dCB770D593f1D35bc2B11 +stableDebtMANA: 0x8DB6b6aE3c096E84B9818545974d1577E37Bcb97 +variableDebtMANA: 0x945ea0cf8986724ec075bE09C503c822fF8Ebb75 +aLINK: 0x778c890b128CE3936b744F0c8d7290d1F161D888 +strategyLINK: 0xCD8C6429A2975Db9466fCEFf36020166930a11Cb +aMANA: 0x5fd9aE04361262868d5C33cA1545580fC509b34c +strategyMANA: 0x024CC36954EfDbB9CFdda80a5A8c05Bd8DdF0fc8 +stableDebtMKR: 0xd1bD598200b53FC352483dBe36d9d72C085011A4 +variableDebtMKR: 0x49b81af588031Ecc93E20355E9ADC2d720348347 +stableDebtREN: 0x7367fBfEA2643eCbc0816Cc87B91E82B3Eb307aF +variableDebtREN: 0xAD75a04e5B815558a7E6C84c030e857671875934 +aMKR: 0xbEf21bFD5164eA882d74df73BB0862226C3063E9 +strategyMKR: 0x27a99bef2aF3200c6B7a831C61eF692341C7acEe +aREN: 0xe807dCAB5d5e8c5701c089758aAd34869a4c92Ea +strategyREN: 0xD933d804Dcb597Ac8020623ac32CcE3d4cB81b2a +stableDebtSNX: 0x3F33fb4D89eC6Bd516dCa915A3d85F0374d099d5 +variableDebtSNX: 0xD27B891432c9036E9dC95bc4fE9b8FCb61FBa05e +stableDebtSUSD: 0xFe3C98C3daE2F7562f43D1bBD2021FE127Afec38 +variableDebtSUSD: 0x53070063F0fB13C51C0e2186C0130f29aBe5336b +aSNX: 0x96a8C36C19D2A96642F2738b8E0481f159488EaD +strategySNX: 0xa5eB1859FA97E38C0a4257Af0be9085b3B4B7996 +aSUSD: 0x948Bd60Cba5eB8b7A478aE673145FeA13e2Edbe8 +strategySUSD: 0x7C769501542E694a5Dea6B1FCAf52B9270EADcaf +stableDebtTUSD: 0x6c2E76485dFbaFe2FCC6874e531D71ee82db06f6 +variableDebtTUSD: 0x3FA01122234D545d0247bdDbf4865925A53f6551 +stableDebtUSDC: 0xDD7a535Fb8773EBc4Ae653eCCb22F6561F434a9E +variableDebtUSDC: 0x9d1718D33aE17e54D2aE329b6B51511d4371Bf4a +aTUSD: 0x802881960dCD9457F63c4dbe1E9D081b32b011b9 +strategyTUSD: 0xC1f335a47c45d9F15976A1e11Eb3826590AD2a56 +aUSDC: 0x1CC642F9b88f755C1E7fbB9Acb4A990faddBF608 +strategyUSDC: 0x4272DE39F41085769562b2c17Fd5369097E41492 +stableDebtUSDT: 0x372915a5Bed2B0a5ecEdc96e7133A24aDDFA4Bc4 +variableDebtUSDT: 0x78123523ba15F9847D22a6d3f06bBed70E431114 +stableDebtWBTC: 0x6a3aB96987B70E29bc4203f78D09D0aCB85F219D +variableDebtWBTC: 0xcDD6c3f0dA05129f08DB52380C48A9cf698A8CCA +aUSDT: 0xe88141a1642eD64AE739cd2C896009Be73a43486 +strategyUSDT: 0x881036687070243FC119014c41cdd5e3c22f3E50 +aWBTC: 0xE74801a99A51B89dE670132De7d9c18CC2BBE54A +strategyWBTC: 0x55DFA1D5af234B35D457C13B8a58899848A438F8 +stableDebtWETH: 0xD1220D8A82a26C1396cccb5Ee79d3A42D7D3E3da +variableDebtWETH: 0x4f87eBaac31C3d13C376d52A0FABf5f022660C4c +stableDebtYFI: 0xF2dB8bc0dCd0A6C6F25B7f6ACfB9E026ae0e7494 +variableDebtYFI: 0xce3529624a1f3Ea5DBC1AB130eBeA8211E3b602F +aWETH: 0x7e4b842FFc0598C1f5D8b8A1e2C7AD29E9F233C7 +strategyWETH: 0x52Ac4c1Dbc0263b2FD6AD065B27576d0E7d925B9 +aYFI: 0x895D60248de2edc34C99f1B45d8Dd1731656Df51 +strategyYFI: 0x3cE6D0B4b6dc27C725fA94903Fb33d73bE75e9D7 +stableDebtZRX: 0xF78Fbf3b21aF8Bce2efA3614E507735573c578CC +variableDebtZRX: 0x9Ae60ba71A28a1d738a2FDFC1D0439B33f3f0B1F +aZRX: 0x80aB7B8EfeA24C2D2Ca22315BFa99E03f539C568 +strategyZRX: 0x4D2271CFa5587643B8f5919f3EbF64de7aaa9d5c +DelegationAwareAToken: 0xBAdDA897176B5A94FD4A0eCb59678DDA29181963 +StableDebtToken: 0x64Ea58f488aD445235A0afE9256B066572c6Abc8 +VariableDebtToken: 0x8D0206fEBEB380486729b64bB4cfEDC5b354a6D6 +DefaultReserveInterestRateStrategy: 0x3c5408De7435Dfa3eB2aF2Edf5E39385f68F69b2 +LendingPoolCollateralManagerImpl: 0x6602fca48E95F5068506963E3A8930131108048A +LendingPoolCollateralManager: 0x6602fca48E95F5068506963E3A8930131108048A +MockFlashLoanReceiver: 0x1a66D6103F8BBf9204E1618F095a80b3E4817C95 +WalletBalanceProvider: 0x0EBCa695959e5f138Af772FAa44ce1A9C7aEd921 +WETHGateway: 0x8BFFF31B1757da579Bb5B118489568526F7fb6D4 +MintableDelegationERC20: 0x8BFFF31B1757da579Bb5B118489568526F7fb6D4 +MockAToken: 0x8BFFF31B1757da579Bb5B118489568526F7fb6D4 +MockStableDebtToken: 0x0459c841b02Aee8730730C737582c53B20a27288 +MockVariableDebtToken: 0x2530ce07D254eA185E8e0bCC37a39e2FbA3bE548 +SelfdestructTransferMock: 0x0459c841b02Aee8730730C737582c53B20a27288 +UniswapLendingPool: 0xEC42F4C314dE9492cb3Ef7a860270eCDFE0F851a +UniswapLendingPoolConfigurator: 0x672A68Ff1364E87D8f88ad86410449C117fC97A6 +UniswapLendingPoolAddressesProvider: 0x18b9306737eaf6E8FC8e737F488a1AE077b18053 +UniswapLendingPoolImpl: 0xbAc762e2000b6815268587b081Fd17aC25519aD5 +UniswapLendingPoolConfiguratorImpl: 0xAa7BC1924711B77A0F3Aaebdd550BfeDDDbaf3cd +UniswapPriceOracle: 0xFf130817Aa9863B3D809A2A11617c05646245d80 +UniswapAaveOracle: 0xE91bBe8ee03560E3dda2786f95335F5399813Ca0 +UniswapLendingRateOracle: 0x4977FC58783ceBCC310311C800B786EcAf45F98f +stableDebtWETHDAI: 0x84fF0147dDD2acA72407CfEB7EabCd2b7E49d949 +variableDebtWETHDAI: 0x35A1E1Be236899ab7B63a81127ab522d76A26B3e +aWETHDAI: 0x591D75Ea272E9F22fC4B20Fc4C4E03d8c126b1AB +strategyWETHDAI: 0xF4040B68C37eE6F1324470f48D05cCEC50819b2E +stableDebtWETHWBTC: 0x5a41efF010872DB9a2CA0b47b8b757f37dc35A7f +variableDebtWETHWBTC: 0xee0382a3E9ADeAaA670c425D51ad5F8022c6d9F8 +aWETHWBTC: 0x4dA415c7aDaC37c3d710B5D24b62c6f4a5aF6e5F +strategyWETHWBTC: 0xf0c3F1cd72eA0a1F4e0e98B2e0702fA63a9F9faF +UniswapLendingPoolCollateralManagerImpl: 0x9D2F6Ec881323E78f27d58b996b81EaBCEF8eC58 +UniswapLendingPoolCollateralManager: 0x9D2F6Ec881323E78f27d58b996b81EaBCEF8eC58 +UniswapMockFlashLoanReceiver: 0xad17D0b25259128C968dbCa61CB5864C78004DBE +UniswapWalletBalanceProvider: 0x6Ac05758229c725A6d14F0ae7088985D9B251Fb2 +UniswapWETHGateway: 0xb2B548BE73010C188C083c510d255Aed74843b05 \ No newline at end of file From 4637476bbd547f87a31a94cf70ae74e3a8962b97 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 30 Dec 2020 01:04:06 -0500 Subject: [PATCH 005/219] Removed UNI prefix, cleaned up --- helpers/types.ts | 32 +++++++++++--------------------- markets/aave/commons.ts | 9 ++------- markets/uniswap/commons.ts | 23 +++++++++-------------- markets/uniswap/index.ts | 14 +++++++------- 4 files changed, 29 insertions(+), 49 deletions(-) diff --git a/helpers/types.ts b/helpers/types.ts index 9c15dd13..664e3e62 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -215,13 +215,8 @@ export interface iAssetBase { USD: T; REN: T; ENJ: T; - UNI_WETH: T; - UNI_WBTC: T; - UNI_DAI: T; - UNI_USDC: T; - UNI_USDT: T; - UNI_WETHDAI: T; - UNI_WETHWBTC: T; + WETHDAI: T; + WETHWBTC: T; } export type iAssetsWithoutETH = Omit, 'ETH'>; @@ -254,13 +249,13 @@ export type iAavePoolAssets = Pick< export type iUniswapPoolAssets = Pick< iAssetsWithoutUSD, - | 'UNI_DAI' - | 'UNI_USDC' - | 'UNI_USDT' - | 'UNI_WBTC' - | 'UNI_WETH' - | 'UNI_WETHDAI' - | 'UNI_WETHWBTC' + | 'DAI' + | 'USDC' + | 'USDT' + | 'WBTC' + | 'WETH' + | 'WETHDAI' + | 'WETHWBTC' >; export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; @@ -291,13 +286,8 @@ export enum TokenContractId { YFI = 'YFI', UNI = 'UNI', ENJ = 'ENJ', - UNI_WETH = 'WETH', - UNI_WBTC = 'WBTC', - UNI_DAI = 'DAI', - UNI_USDC = 'USDC', - UNI_USDT = 'USDT', - UNI_WETHDAI = 'WETHDAI', - UNI_WETHWBTC = 'WETHWBTC', + WETHDAI = 'WETHDAI', + WETHWBTC = 'WETHWBTC', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index e059c961..fecd714f 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -23,13 +23,8 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), - UNI_WETH:oneEther.toFixed(), - UNI_WBTC: oneEther.multipliedBy('47.332685').toFixed(), - UNI_DAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - UNI_USDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - UNI_USDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - UNI_WETHDAI: oneEther.multipliedBy('22.407436').toFixed(), - UNI_WETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), + WETHDAI: oneEther.multipliedBy('22.407436').toFixed(), + WETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; // ---------------- diff --git a/markets/uniswap/commons.ts b/markets/uniswap/commons.ts index c12b4570..660a210a 100644 --- a/markets/uniswap/commons.ts +++ b/markets/uniswap/commons.ts @@ -23,13 +23,8 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), - UNI_WETH:oneEther.toFixed(), - UNI_WBTC: oneEther.multipliedBy('47.332685').toFixed(), - UNI_DAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - UNI_USDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - UNI_USDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - UNI_WETHDAI: oneEther.multipliedBy('22.407436').toFixed(), - UNI_WETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), + WETHDAI: oneEther.multipliedBy('22.407436').toFixed(), + WETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; // ---------------- @@ -59,25 +54,25 @@ export const CommonsConfig: ICommonConfiguration = { }, // TODO: reorg alphabetically, checking the reason of tests failing LendingRateOracleRatesCommon: { - UNI_WETH: { + WETH: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - UNI_DAI: { + DAI: { borrowRate: oneRay.multipliedBy(0.039).toFixed(), }, - UNI_USDC: { + USDC: { borrowRate: oneRay.multipliedBy(0.039).toFixed(), }, - UNI_USDT: { + USDT: { borrowRate: oneRay.multipliedBy(0.035).toFixed(), }, - UNI_WBTC: { + WBTC: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - UNI_WETHDAI: { + WETHDAI: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UNI_WETHWBTC: { + WETHWBTC: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, }, diff --git a/markets/uniswap/index.ts b/markets/uniswap/index.ts index d92518df..37daa4af 100644 --- a/markets/uniswap/index.ts +++ b/markets/uniswap/index.ts @@ -21,13 +21,13 @@ export const UniswapConfig: IUniswapConfiguration = { MarketId: 'Uniswap V2 market', ProviderId: 2, ReservesConfig: { - UNI_DAI: strategyDAI, - UNI_USDC: strategyUSDC, - UNI_USDT: strategyUSDT, - UNI_WBTC: strategyWBTC, - UNI_WETH: strategyWETH, - UNI_WETHDAI: strategyWETHDAI, - UNI_WETHWBTC: strategyWETHWBTC + DAI: strategyDAI, + USDC: strategyUSDC, + USDT: strategyUSDT, + WBTC: strategyWBTC, + WETH: strategyWETH, + WETHDAI: strategyWETHDAI, + WETHWBTC: strategyWETHWBTC }, ReserveAssets: { [eEthereumNetwork.buidlerevm]: {}, From 5f4798f4bd2b9eb5b8fd48a7346abe0c7c570612 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 1 Jan 2021 17:43:19 -0500 Subject: [PATCH 006/219] Updated readme for clarity --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8e4b0049..d5d9b6bc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -### Uniswap V2 Market Aave Fork +### Uniswap V2 Liquidity Pool Market Aave Fork ``` .///. .///. //. .// `/////////////- `++:++` .++:++` :++` `++: `++:......---.` From 1669d6587a5d40477e9f75b1924cc24aa6d24307 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 1 Jan 2021 21:14:02 -0500 Subject: [PATCH 007/219] Fixed UNI prefix error in setup.spec --- tasks/dev/7_uniswap_market.ts | 1 + test/__setup.spec.ts | 10 +++------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/tasks/dev/7_uniswap_market.ts b/tasks/dev/7_uniswap_market.ts index aa73fc40..3703f9bb 100644 --- a/tasks/dev/7_uniswap_market.ts +++ b/tasks/dev/7_uniswap_market.ts @@ -139,6 +139,7 @@ task( ProtocolGlobalParams: {UsdAddress, MockUsdPriceInWei}, LendingRateOracleRatesCommon, } = poolConfig as ICommonConfiguration; + console.log("Initialized mocks, global params and lending rate oracle rates"); const defaultTokenList = { diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index 51542de9..e464b47f 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -97,6 +97,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const addressList = await Promise.all( (await DRE.ethers.getSigners()).map((signer) => signer.getAddress()) ); + console.log(addressList); await waitForTx(await addressesProvider.setEmergencyAdmin(addressList[2])); @@ -159,13 +160,8 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { REN: mockTokens.REN.address, UNI: mockTokens.UNI.address, ENJ: mockTokens.ENJ.address, - UNI_WETH: mockTokens.WETH.address, - UNI_WBTC: mockTokens.WBTC.address, - UNI_DAI: mockTokens.DAI.address, - UNI_USDC: mockTokens.USDC.address, - UNI_USDT: mockTokens.USDT.address, - UNI_WETHDAI: mockTokens.UNI_WETHDAI.address, - UNI_WETHWBTC: mockTokens.UNI_WETHWBTC.address, + WETHDAI: mockTokens.WETHDAI.address, + WETHWBTC: mockTokens.WETHWBTC.address, USD: USD_ADDRESS, }, fallbackOracle From ced0bc3dfe480129ddf06e95c063fb51a8dbf2de Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 7 Jan 2021 20:27:39 -0500 Subject: [PATCH 008/219] Setup testing on Kovan. Error on oracle deployment --- markets/uniswap/commons.ts | 6 ++++-- markets/uniswap/index.ts | 4 ++-- package.json | 1 + tasks/full/1_address_provider.ts | 14 ++++++++------ tasks/migrations/aave.dev.ts | 4 ++-- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/markets/uniswap/commons.ts b/markets/uniswap/commons.ts index 660a210a..889b15e3 100644 --- a/markets/uniswap/commons.ts +++ b/markets/uniswap/commons.ts @@ -111,8 +111,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', }, - ProviderRegistryOwner: { - [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', + ProviderRegistryOwner: { // TEMPORARILY USING MY DEPLOYER + [eEthereumNetwork.kovan]: '0x18d9bA2baEfBdE0FF137C4ad031427EF205f1Fd9',//'0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', [eEthereumNetwork.coverage]: '', @@ -181,6 +181,8 @@ export const CommonsConfig: ICommonConfiguration = { YFI: '0xC5d1B1DEb2992738C0273408ac43e1e906086B6C', ZRX: '0xBc3f28Ccc21E9b5856E81E6372aFf57307E2E883', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', + WETHDAI: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + WETHWBTC: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', }, [EthereumNetwork.ropsten]: { AAVE: ZERO_ADDRESS, diff --git a/markets/uniswap/index.ts b/markets/uniswap/index.ts index 37daa4af..e210c630 100644 --- a/markets/uniswap/index.ts +++ b/markets/uniswap/index.ts @@ -39,8 +39,8 @@ export const UniswapConfig: IUniswapConfiguration = { USDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', WBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', WETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', - WETHDAI: '', - WETHWBTC: '', + WETHDAI: '0x7d3A67ab574abD3F9849e5fcDa48c19939d032b4', + WETHWBTC: '0x342e78bf229Cd2a750E80D7D7c2C185455979b91', }, [EthereumNetwork.ropsten]: { // AAVE: '', diff --git a/package.json b/package.json index cd9c9e3e..56c6378e 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "aave:evm:dev:migration": "npm run compile && hardhat aave:dev", "aave:docker:full:migration": "npm run compile && npm run hardhat:docker -- aave:mainnet", "aave:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- aave:mainnet --verify", + "uniswap:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- uniswap:mainnet --verify", "aave:kovan:full:initialize": "npm run hardhat:kovan -- full:initialize-lending-pool --verify --pool Aave", "aave:ropsten:full:migration": "npm run compile && npm run hardhat:ropsten -- aave:mainnet --verify", "aave:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- aave:mainnet", diff --git a/tasks/full/1_address_provider.ts b/tasks/full/1_address_provider.ts index eddc17f8..94506c27 100644 --- a/tasks/full/1_address_provider.ts +++ b/tasks/full/1_address_provider.ts @@ -80,14 +80,16 @@ task( // 2. Deploy address provider and set genesis manager const addressesProvider = await deployLendingPoolAddressesProvider(MarketId, verify); + + // TEMPORARILY DISABLING SEC. 3 FOR KOVAN DEPLOYMENT // 3. Set the provider at the Registry - await waitForTx( - await addressesProviderRegistry.registerAddressesProvider( - addressesProvider.address, - ProviderId - ) - ); + // await waitForTx( + // await addressesProviderRegistry.registerAddressesProvider( + // addressesProvider.address, + // ProviderId + // ) + // ); // 4. Set pool admins diff --git a/tasks/migrations/aave.dev.ts b/tasks/migrations/aave.dev.ts index e92d894d..1fe841fe 100644 --- a/tasks/migrations/aave.dev.ts +++ b/tasks/migrations/aave.dev.ts @@ -29,8 +29,8 @@ task('aave:dev', 'Deploy development enviroment') console.log('4. Deploy oracles'); await localBRE.run('dev:deploy-oracles', {verify, pool: POOL_NAME}); - // console.log('6. Deploy Uniswap market oracles'); - // await localBRE.run('dev:deploy-oracles', {verify, pool: "Uniswap"}); + console.log('6. Deploy Uniswap market oracles'); + await localBRE.run('dev:deploy-oracles', {verify, pool: "Uniswap"}); console.log('5. Initialize lending pool'); await localBRE.run('dev:initialize-lending-pool', {verify, pool: POOL_NAME}); From 84d95038a0afb60ba9771cf8127a4ea965146c0b Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 7 Jan 2021 21:55:24 -0500 Subject: [PATCH 009/219] Fixed Kovan deployment. --- markets/uniswap/commons.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/markets/uniswap/commons.ts b/markets/uniswap/commons.ts index 889b15e3..db319e66 100644 --- a/markets/uniswap/commons.ts +++ b/markets/uniswap/commons.ts @@ -124,7 +124,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', + [eEthereumNetwork.kovan]: '',//'0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', [eEthereumNetwork.main]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', @@ -142,7 +142,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [EthereumNetwork.kovan]: '0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', + [EthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', [EthereumNetwork.ropsten]: ZERO_ADDRESS, [EthereumNetwork.main]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', From 36e5642f24069588fe6dca530524eaa26ce2065b Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Sun, 10 Jan 2021 19:57:58 -0500 Subject: [PATCH 010/219] Removed dev task --- helpers/uniswap-contracts-deployments.ts | 434 +++++++++--------- tasks/dev/7_uniswap_market.ts | 536 +++++++++++------------ tasks/migrations/aave.dev.ts | 4 +- 3 files changed, 487 insertions(+), 487 deletions(-) diff --git a/helpers/uniswap-contracts-deployments.ts b/helpers/uniswap-contracts-deployments.ts index 0c28b324..18681b1d 100644 --- a/helpers/uniswap-contracts-deployments.ts +++ b/helpers/uniswap-contracts-deployments.ts @@ -1,241 +1,241 @@ -import { Contract } from 'ethers'; -import { DRE } from './misc-utils'; -import { - tEthereumAddress, - eContractid, - tStringTokenSmallUnits, - AavePools, - TokenContractId, - iMultiPoolsAssets, - IReserveParams, - PoolConfiguration, - eEthereumNetwork, -} from './types'; +// 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'; +// 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); -}; +// 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 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 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 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 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); +// export const deployGenericLogic = async (reserveLogic: Contract, verify?: boolean) => { +// const genericLogicArtifact = await readArtifact(eContractid.GenericLogic); - const linkedGenericLogicByteCode = linkBytecode(genericLogicArtifact, { - [eContractid.ReserveLogic]: reserveLogic.address, - }); +// const linkedGenericLogicByteCode = linkBytecode(genericLogicArtifact, { +// [eContractid.ReserveLogic]: reserveLogic.address, +// }); - const genericLogicFactory = await DRE.ethers.getContractFactory( - genericLogicArtifact.abi, - linkedGenericLogicByteCode - ); +// const genericLogicFactory = await DRE.ethers.getContractFactory( +// genericLogicArtifact.abi, +// linkedGenericLogicByteCode +// ); - const genericLogic = await (await genericLogicFactory.deploy()).deployed(); - return withSaveAndVerify(genericLogic, eContractid.GenericLogic, [], verify); -}; +// 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); +// 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 linkedValidationLogicByteCode = linkBytecode(validationLogicArtifact, { +// [eContractid.ReserveLogic]: reserveLogic.address, +// [eContractid.GenericLogic]: genericLogic.address, +// }); - const validationLogicFactory = await DRE.ethers.getContractFactory( - validationLogicArtifact.abi, - linkedValidationLogicByteCode - ); +// const validationLogicFactory = await DRE.ethers.getContractFactory( +// validationLogicArtifact.abi, +// linkedValidationLogicByteCode +// ); - const validationLogic = await (await validationLogicFactory.deploy()).deployed(); +// const validationLogic = await (await validationLogicFactory.deploy()).deployed(); - return withSaveAndVerify(validationLogic, eContractid.ValidationLogic, [], verify); -}; +// 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); +// 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, - }; -}; +// // 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 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 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 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 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 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 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 - ); +// export const deployUniswapWETHGateway = async ( +// args: [tEthereumAddress, tEthereumAddress], +// verify?: boolean +// ) => +// withSaveAndVerify( +// await new WETHGatewayFactory(await getFirstSigner()).deploy(...args), +// eContractid.UniswapWETHGateway, +// args, +// verify +// ); diff --git a/tasks/dev/7_uniswap_market.ts b/tasks/dev/7_uniswap_market.ts index 3703f9bb..3d7a2705 100644 --- a/tasks/dev/7_uniswap_market.ts +++ b/tasks/dev/7_uniswap_market.ts @@ -1,323 +1,323 @@ -import { task } from 'hardhat/config'; -import { - deployATokensAndRatesHelper, - deployStableAndVariableTokensHelper, - deployAaveProtocolDataProvider, - deployLendingPoolAddressesProvider, //Test -} from '../../helpers/contracts-deployments'; -import { - deployUniswapLendingPoolAddressesProvider, - deployUniswapLendingPool, - deployUniswapLendingPoolConfigurator, - deployUniswapPriceOracle, - deployUniswapAaveOracle, - deployUniswapLendingRateOracle, - deployUniswapLendingPoolCollateralManager, - deployUniswapMockFlashLoanReceiver, - deployUniswapWETHGateway, - deployUniswapWalletBalancerProvider, -} from '../../helpers/uniswap-contracts-deployments'; -import { tEthereumAddress, - eContractid, - AavePools, - ICommonConfiguration, - iAssetBase, - TokenContractId, - IMarketRates, -} from '../../helpers/types'; -import { - getLendingPoolAddressesProviderRegistry, - getLendingPoolAddressesProvider, //Test - getLendingPool, - getLendingPoolConfiguratorProxy, - getAllMockedTokens, - getPairsTokenAggregator, -} from '../../helpers/contracts-getters'; -import { waitForTx, filterMapBy } from '../../helpers/misc-utils'; -import { UniswapConfig } from '../../markets/uniswap'; -import { insertContractAddressInDb } from '../../helpers/contracts-helpers'; -import { - setInitialAssetPricesInOracle, - deployAllMockAggregators, - setInitialMarketRatesInRatesOracleByHelper, -} from '../../helpers/oracles-helpers'; -import {getAllAggregatorsAddresses, getAllTokenAddresses} from '../../helpers/mock-helpers'; -import { - ConfigNames, - getReservesConfigByPool, - getTreasuryAddress, - loadPoolConfig, - getWethAddress, -} from '../../helpers/configuration'; -import { - configureReservesByHelper, - initReservesByHelper, -} from '../../helpers/init-helpers'; -import { ZERO_ADDRESS } from '../../helpers/constants'; +// import { task } from 'hardhat/config'; +// import { +// deployATokensAndRatesHelper, +// deployStableAndVariableTokensHelper, +// deployAaveProtocolDataProvider, +// deployLendingPoolAddressesProvider, //Test +// } from '../../helpers/contracts-deployments'; +// import { +// deployUniswapLendingPoolAddressesProvider, +// deployUniswapLendingPool, +// deployUniswapLendingPoolConfigurator, +// deployUniswapPriceOracle, +// deployUniswapAaveOracle, +// deployUniswapLendingRateOracle, +// deployUniswapLendingPoolCollateralManager, +// deployUniswapMockFlashLoanReceiver, +// deployUniswapWETHGateway, +// deployUniswapWalletBalancerProvider, +// } from '../../helpers/uniswap-contracts-deployments'; +// import { tEthereumAddress, +// eContractid, +// AavePools, +// ICommonConfiguration, +// iAssetBase, +// TokenContractId, +// IMarketRates, +// } from '../../helpers/types'; +// import { +// getLendingPoolAddressesProviderRegistry, +// getLendingPoolAddressesProvider, //Test +// getLendingPool, +// getLendingPoolConfiguratorProxy, +// getAllMockedTokens, +// getPairsTokenAggregator, +// } from '../../helpers/contracts-getters'; +// import { waitForTx, filterMapBy } from '../../helpers/misc-utils'; +// import { UniswapConfig } from '../../markets/uniswap'; +// import { insertContractAddressInDb } from '../../helpers/contracts-helpers'; +// import { +// setInitialAssetPricesInOracle, +// deployAllMockAggregators, +// setInitialMarketRatesInRatesOracleByHelper, +// } from '../../helpers/oracles-helpers'; +// import {getAllAggregatorsAddresses, getAllTokenAddresses} from '../../helpers/mock-helpers'; +// import { +// ConfigNames, +// getReservesConfigByPool, +// getTreasuryAddress, +// loadPoolConfig, +// getWethAddress, +// } from '../../helpers/configuration'; +// import { +// configureReservesByHelper, +// initReservesByHelper, +// } from '../../helpers/init-helpers'; +// import { ZERO_ADDRESS } from '../../helpers/constants'; -const pool = ConfigNames.Uniswap; -/** - * @dev addressesProvider is actually created here, so we don't need to use getAddressesProvider - */ -task( - 'dev:deploy-uniswap-market', - 'Deploy uniswap market' -) - .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({ verify }, localBRE) => { - await localBRE.run('set-DRE'); +// const pool = ConfigNames.Uniswap; +// /** +// * @dev addressesProvider is actually created here, so we don't need to use getAddressesProvider +// */ +// task( +// 'dev:deploy-uniswap-market', +// 'Deploy uniswap market' +// ) +// .addFlag('verify', 'Verify contracts at Etherscan') +// .setAction(async ({ verify }, localBRE) => { +// await localBRE.run('set-DRE'); - const admin = await (await localBRE.ethers.getSigners())[0].getAddress(); +// const admin = await (await localBRE.ethers.getSigners())[0].getAddress(); - const testProvider = await getLendingPoolAddressesProvider(); - console.log("Addresses provider from function (pre re-deploy):", testProvider.address); - const addressesProvider = await deployLendingPoolAddressesProvider(UniswapConfig.MarketId, verify); - console.log("Addresses provider in execution::", addressesProvider.address) +// const testProvider = await getLendingPoolAddressesProvider(); +// console.log("Addresses provider from function (pre re-deploy):", testProvider.address); +// const addressesProvider = await deployLendingPoolAddressesProvider(UniswapConfig.MarketId, verify); +// console.log("Addresses provider in execution::", addressesProvider.address) - const testProviderPost = await getLendingPoolAddressesProvider(); - console.log("Addresses provider from function (pre re-deploy):", testProviderPost.address); - console.log("Addresses provider from function (post re-deploy) should be different:") - await waitForTx(await addressesProvider.setPoolAdmin(admin)); +// const testProviderPost = await getLendingPoolAddressesProvider(); +// console.log("Addresses provider from function (pre re-deploy):", testProviderPost.address); +// console.log("Addresses provider from function (post re-deploy) should be different:") +// await waitForTx(await addressesProvider.setPoolAdmin(admin)); - const addressesProviderRegistry = await getLendingPoolAddressesProviderRegistry(); - await waitForTx( - await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 1) - ); - console.log(addressesProvider.address); +// const addressesProviderRegistry = await getLendingPoolAddressesProviderRegistry(); +// await waitForTx( +// await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 1) +// ); +// console.log(addressesProvider.address); - /** - * LENDING POOL DEPLOYMENT - */ - const lendingPoolImpl = await deployUniswapLendingPool(verify); +// /** +// * LENDING POOL DEPLOYMENT +// */ +// const lendingPoolImpl = await deployUniswapLendingPool(verify); - await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address)); +// await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address)); - const address = await addressesProvider.getLendingPool(); - console.log("UNISWAP MARKET LENDING POOL:", address); - const lendingPoolProxy = await getLendingPool(address); - await insertContractAddressInDb(eContractid.UniswapLendingPool, lendingPoolProxy.address); +// const address = await addressesProvider.getLendingPool(); +// console.log("UNISWAP MARKET LENDING POOL:", address); +// const lendingPoolProxy = await getLendingPool(address); +// await insertContractAddressInDb(eContractid.UniswapLendingPool, lendingPoolProxy.address); - const lendingPoolConfiguratorImpl = await deployUniswapLendingPoolConfigurator(verify); +// const lendingPoolConfiguratorImpl = await deployUniswapLendingPoolConfigurator(verify); - // Set lending pool conf impl to Address Provider - await waitForTx( - await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImpl.address) - ); +// // Set lending pool conf impl to Address Provider +// await waitForTx( +// await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImpl.address) +// ); - const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy( - await addressesProvider.getLendingPoolConfigurator() - ); +// const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy( +// await addressesProvider.getLendingPoolConfigurator() +// ); - await insertContractAddressInDb( - eContractid.UniswapLendingPoolConfigurator, - lendingPoolConfiguratorProxy.address - ); +// await insertContractAddressInDb( +// eContractid.UniswapLendingPoolConfigurator, +// lendingPoolConfiguratorProxy.address +// ); - // Deploy deployment helpers - await deployStableAndVariableTokensHelper( - [lendingPoolProxy.address, addressesProvider.address], - verify - ); - await deployATokensAndRatesHelper( - [lendingPoolProxy.address, addressesProvider.address, lendingPoolConfiguratorProxy.address], - verify - ); +// // Deploy deployment helpers +// await deployStableAndVariableTokensHelper( +// [lendingPoolProxy.address, addressesProvider.address], +// verify +// ); +// await deployATokensAndRatesHelper( +// [lendingPoolProxy.address, addressesProvider.address, lendingPoolConfiguratorProxy.address], +// verify +// ); - /** - * @dev Oracle deployment section - */ +// /** +// * @dev Oracle deployment section +// */ - console.log("Uniswap oracle deployment beginning.") - const poolConfig = loadPoolConfig(pool); - console.log("Initialized pool config..."); +// console.log("Uniswap oracle deployment beginning.") +// const poolConfig = loadPoolConfig(pool); +// console.log("Initialized pool config..."); - const { - Mocks: {AllAssetsInitialPrices}, - ProtocolGlobalParams: {UsdAddress, MockUsdPriceInWei}, - LendingRateOracleRatesCommon, - } = poolConfig as ICommonConfiguration; +// const { +// Mocks: {AllAssetsInitialPrices}, +// ProtocolGlobalParams: {UsdAddress, MockUsdPriceInWei}, +// LendingRateOracleRatesCommon, +// } = poolConfig as ICommonConfiguration; - console.log("Initialized mocks, global params and lending rate oracle rates"); +// console.log("Initialized mocks, global params and lending rate oracle rates"); - const defaultTokenList = { - ...Object.fromEntries(Object.keys(TokenContractId).map((symbol) => [symbol, ''])), - USD: UsdAddress, - } as iAssetBase; +// const defaultTokenList = { +// ...Object.fromEntries(Object.keys(TokenContractId).map((symbol) => [symbol, ''])), +// USD: UsdAddress, +// } as iAssetBase; - console.log("Initialized defaultTokenList"); +// console.log("Initialized defaultTokenList"); - const mockTokens = await getAllMockedTokens(); +// const mockTokens = await getAllMockedTokens(); - console.log("Initialized mock tokens"); +// console.log("Initialized mock tokens"); - const mockTokensAddress = Object.keys(mockTokens).reduce>((prev, curr) => { - prev[curr as keyof iAssetBase] = mockTokens[curr].address; - return prev; - }, defaultTokenList); - console.log(mockTokensAddress); - console.log("Initialized mock tokens addresses"); +// const mockTokensAddress = Object.keys(mockTokens).reduce>((prev, curr) => { +// prev[curr as keyof iAssetBase] = mockTokens[curr].address; +// return prev; +// }, defaultTokenList); +// console.log(mockTokensAddress); +// console.log("Initialized mock tokens addresses"); - // No need to re-initialize addressesProvider and admin +// // No need to re-initialize addressesProvider and admin - const fallbackOracle = await deployUniswapPriceOracle(verify); - console.log("Deployed fallback price oracle"); +// const fallbackOracle = await deployUniswapPriceOracle(verify); +// console.log("Deployed fallback price oracle"); - await waitForTx(await fallbackOracle.setEthUsdPrice(MockUsdPriceInWei)); - console.log("set fallback ETH USD price"); +// await waitForTx(await fallbackOracle.setEthUsdPrice(MockUsdPriceInWei)); +// console.log("set fallback ETH USD price"); - await setInitialAssetPricesInOracle(AllAssetsInitialPrices, mockTokensAddress, fallbackOracle); - console.log("Set initial asset prices in oracle"); +// await setInitialAssetPricesInOracle(AllAssetsInitialPrices, mockTokensAddress, fallbackOracle); +// console.log("Set initial asset prices in oracle"); - const mockAggregators = await deployAllMockAggregators(AllAssetsInitialPrices, verify); - console.log("Deployed mock aggregators"); +// const mockAggregators = await deployAllMockAggregators(AllAssetsInitialPrices, verify); +// console.log("Deployed mock aggregators"); - const allTokenAddresses = getAllTokenAddresses(mockTokens); - console.log("Got all mock token addresses"); +// const allTokenAddresses = getAllTokenAddresses(mockTokens); +// console.log("Got all mock token addresses"); - const allAggregatorsAddresses = getAllAggregatorsAddresses(mockAggregators); - console.log("Got all aggregator addresses"); - console.log("allTokenAddresses object: \n", allTokenAddresses); - //Should modify this to potentially contain only the tokens in the Uniswap market - // const [tokens, aggregators] = getPairsTokenAggregator( - // allTokenAddresses, - // allAggregatorsAddresses - // ); - // console.log("Got \"pairsToken aggregator\""); - // console.log("Tokens: \n", tokens); +// const allAggregatorsAddresses = getAllAggregatorsAddresses(mockAggregators); +// console.log("Got all aggregator addresses"); +// console.log("allTokenAddresses object: \n", allTokenAddresses); +// //Should modify this to potentially contain only the tokens in the Uniswap market +// // const [tokens, aggregators] = getPairsTokenAggregator( +// // allTokenAddresses, +// // allAggregatorsAddresses +// // ); +// // console.log("Got \"pairsToken aggregator\""); +// // console.log("Tokens: \n", tokens); - // const assetAddressIndex = Object.keys(allReservesAddresses).findIndex( - // (value) => value === assetSymbol - // ); - // const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[ - // assetAddressIndex - // ]; - // assetAddresses.push(assetAddress); +// // const assetAddressIndex = Object.keys(allReservesAddresses).findIndex( +// // (value) => value === assetSymbol +// // ); +// // const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[ +// // assetAddressIndex +// // ]; +// // assetAddresses.push(assetAddress); - // await deployUniswapAaveOracle( - // [tokens, aggregators, fallbackOracle.address, await getWethAddress(poolConfig)], - // verify - // ); - console.log("Deployed Uniswap Aave oracle"); +// // await deployUniswapAaveOracle( +// // [tokens, aggregators, fallbackOracle.address, await getWethAddress(poolConfig)], +// // verify +// // ); +// console.log("Deployed Uniswap Aave oracle"); - await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address)); - console.log("Set price oracle in addresses provider"); +// await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address)); +// console.log("Set price oracle in addresses provider"); - const lendingRateOracle = await deployUniswapLendingRateOracle(verify); - console.log("Deployed lendingRateOracle"); +// const lendingRateOracle = await deployUniswapLendingRateOracle(verify); +// console.log("Deployed lendingRateOracle"); - await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); - console.log("Set lending rate oracle in addresses provider"); +// await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); +// console.log("Set lending rate oracle in addresses provider"); - const {USD, ...tokensAddressesWithoutUsd} = allTokenAddresses; - console.log("Initialized object with token addresses & usd") +// const {USD, ...tokensAddressesWithoutUsd} = allTokenAddresses; +// console.log("Initialized object with token addresses & usd") - const allReservesAddresses = { - ...tokensAddressesWithoutUsd, - }; - console.log("Initialized object with all reserve addresses, allReservesAddresses:"); - console.log(allReservesAddresses); +// const allReservesAddresses = { +// ...tokensAddressesWithoutUsd, +// }; +// console.log("Initialized object with all reserve addresses, allReservesAddresses:"); +// console.log(allReservesAddresses); - console.log("LendingRateOracleRatesCommon: \n", LendingRateOracleRatesCommon); - // - // -- test - // - const [tokens, aggregators] = getPairsTokenAggregator( - allTokenAddresses, - allAggregatorsAddresses - ); - console.log("Got \"pairsToken aggregator\""); - console.log("Tokens: \n", tokens); - const assetAddresses: string[] = []; - const aggregatorAddresses: string[] = []; - for (const [assetSymbol, {borrowRate}] of Object.entries(LendingRateOracleRatesCommon) as [ - string, - IMarketRates - ][]) { - const assetAddressIndex = Object.keys(allReservesAddresses).findIndex( - (value) => value === assetSymbol - ); - const [, assetAddress] = (Object.entries(allReservesAddresses) as [string, string][])[ - assetAddressIndex - ]; +// console.log("LendingRateOracleRatesCommon: \n", LendingRateOracleRatesCommon); +// // +// // -- test +// // +// const [tokens, aggregators] = getPairsTokenAggregator( +// allTokenAddresses, +// allAggregatorsAddresses +// ); +// console.log("Got \"pairsToken aggregator\""); +// console.log("Tokens: \n", tokens); +// const assetAddresses: string[] = []; +// const aggregatorAddresses: string[] = []; +// for (const [assetSymbol, {borrowRate}] of Object.entries(LendingRateOracleRatesCommon) as [ +// string, +// IMarketRates +// ][]) { +// const assetAddressIndex = Object.keys(allReservesAddresses).findIndex( +// (value) => value === assetSymbol +// ); +// const [, assetAddress] = (Object.entries(allReservesAddresses) as [string, string][])[ +// assetAddressIndex +// ]; - const [, aggregatorAddress] = (Object.entries(allAggregatorsAddresses) as [string, string][])[ - assetAddressIndex - ]; - aggregatorAddresses.push(aggregatorAddress); - assetAddresses.push(assetAddress); - } - console.log("\nPRICE ORACLE PARAMS:\nassetAddresses: %s\naggregatorAddresses: %s", assetAddresses, aggregatorAddresses); - await deployUniswapAaveOracle( - [assetAddresses, aggregatorAddresses, fallbackOracle.address, await getWethAddress(poolConfig)], - verify - ); - // - // -- test end - // - console.log("TEST END-----------------------------------------------------------------------"); - await setInitialMarketRatesInRatesOracleByHelper( - LendingRateOracleRatesCommon, - allReservesAddresses, - lendingRateOracle, - admin - ); +// const [, aggregatorAddress] = (Object.entries(allAggregatorsAddresses) as [string, string][])[ +// assetAddressIndex +// ]; +// aggregatorAddresses.push(aggregatorAddress); +// assetAddresses.push(assetAddress); +// } +// console.log("\nPRICE ORACLE PARAMS:\nassetAddresses: %s\naggregatorAddresses: %s", assetAddresses, aggregatorAddresses); +// await deployUniswapAaveOracle( +// [assetAddresses, aggregatorAddresses, fallbackOracle.address, await getWethAddress(poolConfig)], +// verify +// ); +// // +// // -- test end +// // +// console.log("TEST END-----------------------------------------------------------------------"); +// await setInitialMarketRatesInRatesOracleByHelper( +// LendingRateOracleRatesCommon, +// allReservesAddresses, +// lendingRateOracle, +// admin +// ); - console.log("Task complete"); +// console.log("Task complete"); - /** - * @dev Initialization - */ +// /** +// * @dev Initialization +// */ - // No need to initialize poolConfig, mockTokens, allTokenAddresses, admin and - // addressesProvider and protoReservesAddresses (we use allReserveAddresses) +// // No need to initialize poolConfig, mockTokens, allTokenAddresses, admin and +// // addressesProvider and protoReservesAddresses (we use allReserveAddresses) - const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address, verify); +// const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address, verify); - const reservesParams = getReservesConfigByPool(AavePools.uniswap); +// const reservesParams = getReservesConfigByPool(AavePools.uniswap); - const treasuryAddress = await getTreasuryAddress(poolConfig); +// const treasuryAddress = await getTreasuryAddress(poolConfig); - await initReservesByHelper( - addressesProvider, - reservesParams, - allReservesAddresses, - admin, - treasuryAddress, - ZERO_ADDRESS, - verify - ); +// await initReservesByHelper( +// addressesProvider, +// reservesParams, +// allReservesAddresses, +// admin, +// treasuryAddress, +// ZERO_ADDRESS, +// verify +// ); - await configureReservesByHelper( - addressesProvider, - reservesParams, - allReservesAddresses, - testHelpers, - admin - ); +// await configureReservesByHelper( +// addressesProvider, +// reservesParams, +// allReservesAddresses, +// testHelpers, +// admin +// ); - const collateralManager = await deployUniswapLendingPoolCollateralManager(verify); - await waitForTx( - await addressesProvider.setLendingPoolCollateralManager(collateralManager.address) - ); +// const collateralManager = await deployUniswapLendingPoolCollateralManager(verify); +// await waitForTx( +// await addressesProvider.setLendingPoolCollateralManager(collateralManager.address) +// ); - const mockFlashLoanReceiver = await deployUniswapMockFlashLoanReceiver( - addressesProvider.address, - verify - ); +// const mockFlashLoanReceiver = await deployUniswapMockFlashLoanReceiver( +// addressesProvider.address, +// verify +// ); - await insertContractAddressInDb( - eContractid.UniswapMockFlashLoanReceiver, - mockFlashLoanReceiver.address - ); +// await insertContractAddressInDb( +// eContractid.UniswapMockFlashLoanReceiver, +// mockFlashLoanReceiver.address +// ); - await deployUniswapWalletBalancerProvider(verify); +// await deployUniswapWalletBalancerProvider(verify); - await insertContractAddressInDb(eContractid.AaveProtocolDataProvider, testHelpers.address); +// await insertContractAddressInDb(eContractid.AaveProtocolDataProvider, testHelpers.address); - const lendingPoolAddress = await addressesProvider.getLendingPool(); - const wethAddress = await getWethAddress(poolConfig); - await deployUniswapWETHGateway([wethAddress, lendingPoolAddress]); - }); +// const lendingPoolAddress = await addressesProvider.getLendingPool(); +// const wethAddress = await getWethAddress(poolConfig); +// await deployUniswapWETHGateway([wethAddress, lendingPoolAddress]); +// }); diff --git a/tasks/migrations/aave.dev.ts b/tasks/migrations/aave.dev.ts index 1fe841fe..ed208c6b 100644 --- a/tasks/migrations/aave.dev.ts +++ b/tasks/migrations/aave.dev.ts @@ -35,8 +35,8 @@ task('aave:dev', 'Deploy development enviroment') console.log('5. Initialize lending pool'); await localBRE.run('dev:initialize-lending-pool', {verify, pool: POOL_NAME}); - console.log('6. Deploy Uniswap market'); - await localBRE.run('dev:deploy-uniswap-market', {verify}); + // console.log('6. Deploy Uniswap market'); + // await localBRE.run('dev:deploy-uniswap-market', {verify}); console.log('\nFinished migration'); printContracts(); From 95691770abac75a676d7e8d9cd4dca54f4e20bfa Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Sun, 10 Jan 2021 20:05:34 -0500 Subject: [PATCH 011/219] Reset to original state --- helpers/contracts-getters.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index 34b0d134..65834cc6 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -153,9 +153,7 @@ export const getAllMockedTokens = async () => { const tokens: MockTokenMap = await Object.keys(TokenContractId).reduce>( async (acc, tokenSymbol) => { const accumulator = await acc; - console.log("getAllMockedTokens: got accumulator, next token:", tokenSymbol.toUpperCase()); const address = db.get(`${tokenSymbol.toUpperCase()}.${DRE.network.name}`).value().address; - console.log("getAllMockedTokens: Initialized address for %s, address: %s", tokenSymbol, address); accumulator[tokenSymbol] = await getMintableERC20(address); return Promise.resolve(acc); }, @@ -177,8 +175,6 @@ export const getPairsTokenAggregator = ( const aggregatorAddressIndex = Object.keys(aggregatorsAddresses).findIndex( (value) => value === tokenSymbol ); - //console.log("getPairsTokenAggregator: tokenSymbol:", tokenSymbol); - //console.log("getPairsTokenAggregator: aggregatorsAddresses:\n\n", aggregatorsAddresses); const [, aggregatorAddress] = (Object.entries(aggregatorsAddresses) as [ string, tEthereumAddress From 587c4df47c084476a0a0cdc3b457057fdfc22c23 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Sun, 10 Jan 2021 20:10:43 -0500 Subject: [PATCH 012/219] Cleanup --- helpers/contracts-deployments.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 66e21be4..739ade34 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -388,7 +388,6 @@ export const deployAllMockTokens = async (verify?: boolean) => { verify ); await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); - console.log("deployAllMockTokens: deployed", tokenSymbol); } return tokens; }; From 0472cc27f25ebc87248f8a70d9e9f1ff56eade53 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Sun, 10 Jan 2021 20:40:23 -0500 Subject: [PATCH 013/219] Cleanup (Removed unneeded dev deployment) --- helpers/init-helpers.ts | 13 +- helpers/oracles-helpers.ts | 7 - helpers/types.ts | 14 - helpers/uniswap-contracts-deployments.ts | 241 ----------------- tasks/dev/3_lending_pool.ts | 6 +- tasks/dev/4_oracles.ts | 58 +--- tasks/dev/5_initialize.ts | 2 - tasks/dev/7_uniswap_market.ts | 323 ----------------------- tasks/full/1_address_provider.ts | 2 +- tasks/full/3_oracles.ts | 7 +- tasks/full/5_initialize.ts | 5 +- tasks/migrations/aave.dev.ts | 10 +- test/__setup.spec.ts | 4 +- test/test | 153 ----------- 14 files changed, 14 insertions(+), 831 deletions(-) delete mode 100644 helpers/uniswap-contracts-deployments.ts delete mode 100644 tasks/dev/7_uniswap_market.ts delete mode 100644 test/test diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 96ec9df7..e80d2f91 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -25,7 +25,6 @@ import { } from './contracts-deployments'; import { ZERO_ADDRESS } from './constants'; import { isZeroAddress } from 'ethereumjs-util'; -import { LendingPoolAddressesProvider } from '../types'; const chooseATokenDeployment = (id: eContractid) => { switch (id) { @@ -39,7 +38,6 @@ const chooseATokenDeployment = (id: eContractid) => { }; export const initReservesByHelper = async ( - addressProvider: LendingPoolAddressesProvider, reservesParams: iMultiPoolsAssets, tokenAddresses: { [symbol: string]: tEthereumAddress }, admin: tEthereumAddress, @@ -51,7 +49,7 @@ export const initReservesByHelper = async ( const stableAndVariableDeployer = await getStableAndVariableTokensHelper(); const atokenAndRatesDeployer = await getATokensAndRatesHelper(); - //const addressProvider = await getLendingPoolAddressesProvider(); + const addressProvider = await getLendingPoolAddressesProvider(); const poolAddress = await addressProvider.getLendingPool(); // Set aTokenAndRatesDeployer as temporal admin @@ -82,7 +80,6 @@ export const initReservesByHelper = async ( Object.entries(reservesParams).length * 4 } txs` ); - console.log("initReservesByHelper: tokenAddresses:", tokenAddresses); for (let reservesChunk of reservesChunks) { // Prepare data const tokens: string[] = []; @@ -98,15 +95,13 @@ export const initReservesByHelper = async ( const reservesDecimals: string[] = []; for (let [assetSymbol, { reserveDecimals }] of reservesChunk) { - console.log("initReservesByHelper: assetSymbol:\n%s", assetSymbol); const assetAddressIndex = Object.keys(tokenAddresses).findIndex( (value) => value === assetSymbol ); - console.log("initReservesByHelper: assetAddressIndex:\n%s", assetAddressIndex); const [, tokenAddress] = (Object.entries(tokenAddresses) as [string, string][])[ assetAddressIndex ]; - console.log("initReservesByHelper: tokenAddress:\n%s", assetAddressIndex); + const reserveParamIndex = Object.keys(reservesParams).findIndex( (value) => value === assetSymbol ); @@ -136,7 +131,6 @@ export const initReservesByHelper = async ( } // Deploy stable and variable deployers and save implementations - // PARAMS HANG IN LOCALHOST console.log("Hanging params:\ntokens:\n %s\n symbols:\n %s \n incentivesController: \n %s ", tokens, symbols, incentivesController); const tx1 = await waitForTx( await stableAndVariableDeployer.initDeployment(tokens, symbols, incentivesController) ); @@ -306,13 +300,12 @@ export const getPairsTokenAggregator = ( }; export const configureReservesByHelper = async ( - addressProvider: LendingPoolAddressesProvider, reservesParams: iMultiPoolsAssets, tokenAddresses: { [symbol: string]: tEthereumAddress }, helpers: AaveProtocolDataProvider, admin: tEthereumAddress ) => { - //const addressProvider = await getLendingPoolAddressesProvider(); + const addressProvider = await getLendingPoolAddressesProvider(); const atokenAndRatesDeployer = await getATokensAndRatesHelper(); const tokens: string[] = []; const symbols: string[] = []; diff --git a/helpers/oracles-helpers.ts b/helpers/oracles-helpers.ts index aaa19976..45cec5e2 100644 --- a/helpers/oracles-helpers.ts +++ b/helpers/oracles-helpers.ts @@ -28,7 +28,6 @@ export const setInitialMarketRatesInRatesOracleByHelper = async ( string, IMarketRates ][]) { - console.log("Current asset symbol:", assetSymbol); const assetAddressIndex = Object.keys(assetsAddresses).findIndex( (value) => value === assetSymbol ); @@ -39,12 +38,6 @@ export const setInitialMarketRatesInRatesOracleByHelper = async ( borrowRates.push(borrowRate); symbols.push(assetSymbol); } - - console.log("---setInitialMarketRatesInRatesOracleByHelper---"); - console.log(assetAddresses); - console.log(symbols); - console.log(borrowRates); - // Set borrow rates per chunks const ratesChunks = 20; const chunkedTokens = chunk(assetAddresses, ratesChunks); diff --git a/helpers/types.ts b/helpers/types.ts index 664e3e62..bbb16389 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -28,41 +28,31 @@ export enum AavePools { export enum eContractid { Example = 'Example', LendingPoolAddressesProvider = 'LendingPoolAddressesProvider', - UniswapLendingPoolAddressesProvider = 'UniswapLendingPoolAddressesProvider', MintableERC20 = 'MintableERC20', MintableDelegationERC20 = 'MintableDelegationERC20', LendingPoolAddressesProviderRegistry = 'LendingPoolAddressesProviderRegistry', LendingPoolParametersProvider = 'LendingPoolParametersProvider', LendingPoolConfigurator = 'LendingPoolConfigurator', - UniswapLendingPoolConfigurator = 'UniswapLendingPoolConfigurator', ValidationLogic = 'ValidationLogic', ReserveLogic = 'ReserveLogic', GenericLogic = 'GenericLogic', LendingPool = 'LendingPool', - UniswapLendingPool = 'UniswapLendingPool', PriceOracle = 'PriceOracle', - UniswapPriceOracle = 'UniswapPriceOracle', Proxy = 'Proxy', MockAggregator = 'MockAggregator', LendingRateOracle = 'LendingRateOracle', - UniswapLendingRateOracle = 'UniswapLendingRateOracle', AaveOracle = 'AaveOracle', - UniswapAaveOracle = 'UniswapAaveOracle', DefaultReserveInterestRateStrategy = 'DefaultReserveInterestRateStrategy', LendingPoolCollateralManager = 'LendingPoolCollateralManager', - UniswapLendingPoolCollateralManager = 'UniswapLendingPoolCollateralManager', InitializableAdminUpgradeabilityProxy = 'InitializableAdminUpgradeabilityProxy', MockFlashLoanReceiver = 'MockFlashLoanReceiver', - UniswapMockFlashLoanReceiver = 'UniswapMockFlashLoanReceiver', WalletBalanceProvider = 'WalletBalanceProvider', - UniswapWalletBalanceProvider = 'UniswapWalletBalanceProvider', AToken = 'AToken', MockAToken = 'MockAToken', DelegationAwareAToken = 'DelegationAwareAToken', MockStableDebtToken = 'MockStableDebtToken', MockVariableDebtToken = 'MockVariableDebtToken', AaveProtocolDataProvider = 'AaveProtocolDataProvider', - UniswapAaveProtocolDataProvider = 'UniswapAaveProtocolDataProvider', IERC20Detailed = 'IERC20Detailed', StableDebtToken = 'StableDebtToken', VariableDebtToken = 'VariableDebtToken', @@ -72,16 +62,12 @@ export enum eContractid { ATokensAndRatesHelper = 'ATokensAndRatesHelper', UiPoolDataProvider = 'UiPoolDataProvider', WETHGateway = 'WETHGateway', - UniswapWETHGateway = 'UniswapWETHGateway', WETH = 'WETH', WETHMocked = 'WETHMocked', SelfdestructTransferMock = 'SelfdestructTransferMock', LendingPoolImpl = 'LendingPoolImpl', - UniswapLendingPoolImpl = 'UniswapLendingPoolImpl', LendingPoolConfiguratorImpl = 'LendingPoolConfiguratorImpl', - UniswapLendingPoolConfiguratorImpl = 'UniswapLendingPoolConfiguratorImpl', LendingPoolCollateralManagerImpl = 'LendingPoolCollateralManagerImpl', - UniswapLendingPoolCollateralManagerImpl = 'UniswapLendingPoolCollateralManagerImpl', } /* diff --git a/helpers/uniswap-contracts-deployments.ts b/helpers/uniswap-contracts-deployments.ts deleted file mode 100644 index 18681b1d..00000000 --- a/helpers/uniswap-contracts-deployments.ts +++ /dev/null @@ -1,241 +0,0 @@ -// 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 -// ); diff --git a/tasks/dev/3_lending_pool.ts b/tasks/dev/3_lending_pool.ts index 692c8386..b1aeb58c 100644 --- a/tasks/dev/3_lending_pool.ts +++ b/tasks/dev/3_lending_pool.ts @@ -18,17 +18,15 @@ task('dev:deploy-lending-pool', 'Deploy lending pool for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') .setAction(async ({verify}, localBRE) => { await localBRE.run('set-DRE'); - // TEST--- CURRENTLY FAILS BECAUSE ALREADY HAS AN IMPLEMENTATION, SHOULD BE DONE BEFORE UNI MARKET TASK + const addressesProvider = await getLendingPoolAddressesProvider(); - + const lendingPoolImpl = await deployLendingPool(verify); // Set lending pool impl to Address Provider await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address)); const address = await addressesProvider.getLendingPool(); - console.log("AAVE MARKET LENDING POOL:", address); - const lendingPoolProxy = await getLendingPool(address); await insertContractAddressInDb(eContractid.LendingPool, lendingPoolProxy.address); diff --git a/tasks/dev/4_oracles.ts b/tasks/dev/4_oracles.ts index b8c29660..97f14c8a 100644 --- a/tasks/dev/4_oracles.ts +++ b/tasks/dev/4_oracles.ts @@ -24,113 +24,57 @@ task('dev:deploy-oracles', 'Deploy oracles for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({verify, pool}, localBRE) => { - await localBRE.run('set-DRE'); const poolConfig = loadPoolConfig(pool); - - console.log("Initialized pool config..."); - const { Mocks: {AllAssetsInitialPrices}, ProtocolGlobalParams: {UsdAddress, MockUsdPriceInWei}, LendingRateOracleRatesCommon, } = poolConfig as ICommonConfiguration; - console.log("Initialized mocks, global params and lending rate oracle rates"); - const defaultTokenList = { ...Object.fromEntries(Object.keys(TokenContractId).map((symbol) => [symbol, ''])), USD: UsdAddress, } as iAssetBase; - - console.log("Initialized defaultTokenList"); - const mockTokens = await getAllMockedTokens(); - - console.log("Initialized mock tokens"); - const mockTokensAddress = Object.keys(mockTokens).reduce>((prev, curr) => { prev[curr as keyof iAssetBase] = mockTokens[curr].address; return prev; }, defaultTokenList); - console.log(mockTokensAddress); - console.log("Initialized mock tokens addresses"); - const addressesProvider = await getLendingPoolAddressesProvider(); - - console.log("Got the addresses provider (check if different both times):", addressesProvider.address); - const admin = await addressesProvider.getPoolAdmin(); - console.log("Got the admin"); - const fallbackOracle = await deployPriceOracle(verify); - - console.log("Deployed fallback price oracle"); - await waitForTx(await fallbackOracle.setEthUsdPrice(MockUsdPriceInWei)); - - console.log("set fallback ETH USD price"); - await setInitialAssetPricesInOracle(AllAssetsInitialPrices, mockTokensAddress, fallbackOracle); - console.log("Set initial asset prices in oracle"); - const mockAggregators = await deployAllMockAggregators(AllAssetsInitialPrices, verify); - console.log("Deployed mock aggregators"); - const allTokenAddresses = getAllTokenAddresses(mockTokens); - - console.log("Got all mock token addresses"); - const allAggregatorsAddresses = getAllAggregatorsAddresses(mockAggregators); - console.log("Got all aggregator addresses"); - const [tokens, aggregators] = getPairsTokenAggregator( allTokenAddresses, allAggregatorsAddresses ); - - console.log("Got \"pairsToken aggregator\""); await deployAaveOracle( [tokens, aggregators, fallbackOracle.address, await getWethAddress(poolConfig)], verify ); - - console.log("Deployed Aave oracle"); - await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address)); - console.log("Set price oracle in addresses provider"); - const lendingRateOracle = await deployLendingRateOracle(verify); - - console.log("Deployed lendingRateOracle"); - await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); - console.log("Set lending rate oracle in addresses provider"); - const {USD, ...tokensAddressesWithoutUsd} = allTokenAddresses; - - console.log("Initialized object with token addresses & usd") - const allReservesAddresses = { ...tokensAddressesWithoutUsd, }; - - console.log("Initialized object with all reserve addresses, allReservesAddresses:"); - console.log(allReservesAddresses); - await setInitialMarketRatesInRatesOracleByHelper( LendingRateOracleRatesCommon, allReservesAddresses, lendingRateOracle, admin ); - - console.log("Task complete"); - }); \ No newline at end of file + }); diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index 9a3896a5..c62f31ce 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -53,7 +53,6 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') const treasuryAddress = await getTreasuryAddress(poolConfig); await initReservesByHelper( - addressesProvider, reservesParams, protoPoolReservesAddresses, admin, @@ -62,7 +61,6 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') verify ); await configureReservesByHelper( - addressesProvider, reservesParams, protoPoolReservesAddresses, testHelpers, diff --git a/tasks/dev/7_uniswap_market.ts b/tasks/dev/7_uniswap_market.ts deleted file mode 100644 index 3d7a2705..00000000 --- a/tasks/dev/7_uniswap_market.ts +++ /dev/null @@ -1,323 +0,0 @@ -// import { task } from 'hardhat/config'; -// import { -// deployATokensAndRatesHelper, -// deployStableAndVariableTokensHelper, -// deployAaveProtocolDataProvider, -// deployLendingPoolAddressesProvider, //Test -// } from '../../helpers/contracts-deployments'; -// import { -// deployUniswapLendingPoolAddressesProvider, -// deployUniswapLendingPool, -// deployUniswapLendingPoolConfigurator, -// deployUniswapPriceOracle, -// deployUniswapAaveOracle, -// deployUniswapLendingRateOracle, -// deployUniswapLendingPoolCollateralManager, -// deployUniswapMockFlashLoanReceiver, -// deployUniswapWETHGateway, -// deployUniswapWalletBalancerProvider, -// } from '../../helpers/uniswap-contracts-deployments'; -// import { tEthereumAddress, -// eContractid, -// AavePools, -// ICommonConfiguration, -// iAssetBase, -// TokenContractId, -// IMarketRates, -// } from '../../helpers/types'; -// import { -// getLendingPoolAddressesProviderRegistry, -// getLendingPoolAddressesProvider, //Test -// getLendingPool, -// getLendingPoolConfiguratorProxy, -// getAllMockedTokens, -// getPairsTokenAggregator, -// } from '../../helpers/contracts-getters'; -// import { waitForTx, filterMapBy } from '../../helpers/misc-utils'; -// import { UniswapConfig } from '../../markets/uniswap'; -// import { insertContractAddressInDb } from '../../helpers/contracts-helpers'; -// import { -// setInitialAssetPricesInOracle, -// deployAllMockAggregators, -// setInitialMarketRatesInRatesOracleByHelper, -// } from '../../helpers/oracles-helpers'; -// import {getAllAggregatorsAddresses, getAllTokenAddresses} from '../../helpers/mock-helpers'; -// import { -// ConfigNames, -// getReservesConfigByPool, -// getTreasuryAddress, -// loadPoolConfig, -// getWethAddress, -// } from '../../helpers/configuration'; -// import { -// configureReservesByHelper, -// initReservesByHelper, -// } from '../../helpers/init-helpers'; -// import { ZERO_ADDRESS } from '../../helpers/constants'; - - -// const pool = ConfigNames.Uniswap; -// /** -// * @dev addressesProvider is actually created here, so we don't need to use getAddressesProvider -// */ -// task( -// 'dev:deploy-uniswap-market', -// 'Deploy uniswap market' -// ) -// .addFlag('verify', 'Verify contracts at Etherscan') -// .setAction(async ({ verify }, localBRE) => { -// await localBRE.run('set-DRE'); - -// const admin = await (await localBRE.ethers.getSigners())[0].getAddress(); - -// const testProvider = await getLendingPoolAddressesProvider(); -// console.log("Addresses provider from function (pre re-deploy):", testProvider.address); -// const addressesProvider = await deployLendingPoolAddressesProvider(UniswapConfig.MarketId, verify); -// console.log("Addresses provider in execution::", addressesProvider.address) - -// const testProviderPost = await getLendingPoolAddressesProvider(); -// console.log("Addresses provider from function (pre re-deploy):", testProviderPost.address); -// console.log("Addresses provider from function (post re-deploy) should be different:") -// await waitForTx(await addressesProvider.setPoolAdmin(admin)); - - -// const addressesProviderRegistry = await getLendingPoolAddressesProviderRegistry(); -// await waitForTx( -// await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 1) -// ); -// console.log(addressesProvider.address); - - -// /** -// * LENDING POOL DEPLOYMENT -// */ -// const lendingPoolImpl = await deployUniswapLendingPool(verify); - -// await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address)); - -// const address = await addressesProvider.getLendingPool(); -// console.log("UNISWAP MARKET LENDING POOL:", address); -// const lendingPoolProxy = await getLendingPool(address); -// await insertContractAddressInDb(eContractid.UniswapLendingPool, lendingPoolProxy.address); - -// const lendingPoolConfiguratorImpl = await deployUniswapLendingPoolConfigurator(verify); - -// // Set lending pool conf impl to Address Provider -// await waitForTx( -// await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImpl.address) -// ); - -// const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy( -// await addressesProvider.getLendingPoolConfigurator() -// ); - -// await insertContractAddressInDb( -// eContractid.UniswapLendingPoolConfigurator, -// lendingPoolConfiguratorProxy.address -// ); - -// // Deploy deployment helpers -// await deployStableAndVariableTokensHelper( -// [lendingPoolProxy.address, addressesProvider.address], -// verify -// ); -// await deployATokensAndRatesHelper( -// [lendingPoolProxy.address, addressesProvider.address, lendingPoolConfiguratorProxy.address], -// verify -// ); - -// /** -// * @dev Oracle deployment section -// */ - -// console.log("Uniswap oracle deployment beginning.") -// const poolConfig = loadPoolConfig(pool); -// console.log("Initialized pool config..."); - -// const { -// Mocks: {AllAssetsInitialPrices}, -// ProtocolGlobalParams: {UsdAddress, MockUsdPriceInWei}, -// LendingRateOracleRatesCommon, -// } = poolConfig as ICommonConfiguration; - -// console.log("Initialized mocks, global params and lending rate oracle rates"); - -// const defaultTokenList = { -// ...Object.fromEntries(Object.keys(TokenContractId).map((symbol) => [symbol, ''])), -// USD: UsdAddress, -// } as iAssetBase; - -// console.log("Initialized defaultTokenList"); - -// const mockTokens = await getAllMockedTokens(); - -// console.log("Initialized mock tokens"); - -// const mockTokensAddress = Object.keys(mockTokens).reduce>((prev, curr) => { -// prev[curr as keyof iAssetBase] = mockTokens[curr].address; -// return prev; -// }, defaultTokenList); -// console.log(mockTokensAddress); -// console.log("Initialized mock tokens addresses"); - -// // No need to re-initialize addressesProvider and admin - -// const fallbackOracle = await deployUniswapPriceOracle(verify); -// console.log("Deployed fallback price oracle"); - -// await waitForTx(await fallbackOracle.setEthUsdPrice(MockUsdPriceInWei)); -// console.log("set fallback ETH USD price"); - -// await setInitialAssetPricesInOracle(AllAssetsInitialPrices, mockTokensAddress, fallbackOracle); -// console.log("Set initial asset prices in oracle"); - -// const mockAggregators = await deployAllMockAggregators(AllAssetsInitialPrices, verify); -// console.log("Deployed mock aggregators"); - -// const allTokenAddresses = getAllTokenAddresses(mockTokens); -// console.log("Got all mock token addresses"); - -// const allAggregatorsAddresses = getAllAggregatorsAddresses(mockAggregators); -// console.log("Got all aggregator addresses"); -// console.log("allTokenAddresses object: \n", allTokenAddresses); -// //Should modify this to potentially contain only the tokens in the Uniswap market -// // const [tokens, aggregators] = getPairsTokenAggregator( -// // allTokenAddresses, -// // allAggregatorsAddresses -// // ); -// // console.log("Got \"pairsToken aggregator\""); -// // console.log("Tokens: \n", tokens); - -// // const assetAddressIndex = Object.keys(allReservesAddresses).findIndex( -// // (value) => value === assetSymbol -// // ); -// // const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[ -// // assetAddressIndex -// // ]; -// // assetAddresses.push(assetAddress); - -// // await deployUniswapAaveOracle( -// // [tokens, aggregators, fallbackOracle.address, await getWethAddress(poolConfig)], -// // verify -// // ); -// console.log("Deployed Uniswap Aave oracle"); - -// await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address)); -// console.log("Set price oracle in addresses provider"); - -// const lendingRateOracle = await deployUniswapLendingRateOracle(verify); -// console.log("Deployed lendingRateOracle"); - -// await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); -// console.log("Set lending rate oracle in addresses provider"); - -// const {USD, ...tokensAddressesWithoutUsd} = allTokenAddresses; -// console.log("Initialized object with token addresses & usd") - -// const allReservesAddresses = { -// ...tokensAddressesWithoutUsd, -// }; -// console.log("Initialized object with all reserve addresses, allReservesAddresses:"); -// console.log(allReservesAddresses); - -// console.log("LendingRateOracleRatesCommon: \n", LendingRateOracleRatesCommon); -// // -// // -- test -// // -// const [tokens, aggregators] = getPairsTokenAggregator( -// allTokenAddresses, -// allAggregatorsAddresses -// ); -// console.log("Got \"pairsToken aggregator\""); -// console.log("Tokens: \n", tokens); -// const assetAddresses: string[] = []; -// const aggregatorAddresses: string[] = []; -// for (const [assetSymbol, {borrowRate}] of Object.entries(LendingRateOracleRatesCommon) as [ -// string, -// IMarketRates -// ][]) { -// const assetAddressIndex = Object.keys(allReservesAddresses).findIndex( -// (value) => value === assetSymbol -// ); -// const [, assetAddress] = (Object.entries(allReservesAddresses) as [string, string][])[ -// assetAddressIndex -// ]; - -// const [, aggregatorAddress] = (Object.entries(allAggregatorsAddresses) as [string, string][])[ -// assetAddressIndex -// ]; -// aggregatorAddresses.push(aggregatorAddress); -// assetAddresses.push(assetAddress); -// } -// console.log("\nPRICE ORACLE PARAMS:\nassetAddresses: %s\naggregatorAddresses: %s", assetAddresses, aggregatorAddresses); -// await deployUniswapAaveOracle( -// [assetAddresses, aggregatorAddresses, fallbackOracle.address, await getWethAddress(poolConfig)], -// verify -// ); -// // -// // -- test end -// // -// console.log("TEST END-----------------------------------------------------------------------"); -// await setInitialMarketRatesInRatesOracleByHelper( -// LendingRateOracleRatesCommon, -// allReservesAddresses, -// lendingRateOracle, -// admin -// ); - -// console.log("Task complete"); - -// /** -// * @dev Initialization -// */ - -// // No need to initialize poolConfig, mockTokens, allTokenAddresses, admin and -// // addressesProvider and protoReservesAddresses (we use allReserveAddresses) - -// const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address, verify); - -// const reservesParams = getReservesConfigByPool(AavePools.uniswap); - -// const treasuryAddress = await getTreasuryAddress(poolConfig); - -// await initReservesByHelper( -// addressesProvider, -// reservesParams, -// allReservesAddresses, -// admin, -// treasuryAddress, -// ZERO_ADDRESS, -// verify -// ); - -// await configureReservesByHelper( -// addressesProvider, -// reservesParams, -// allReservesAddresses, -// testHelpers, -// admin -// ); - -// const collateralManager = await deployUniswapLendingPoolCollateralManager(verify); -// await waitForTx( -// await addressesProvider.setLendingPoolCollateralManager(collateralManager.address) -// ); - -// const mockFlashLoanReceiver = await deployUniswapMockFlashLoanReceiver( -// addressesProvider.address, -// verify -// ); - -// await insertContractAddressInDb( -// eContractid.UniswapMockFlashLoanReceiver, -// mockFlashLoanReceiver.address -// ); - -// await deployUniswapWalletBalancerProvider(verify); - -// await insertContractAddressInDb(eContractid.AaveProtocolDataProvider, testHelpers.address); - -// const lendingPoolAddress = await addressesProvider.getLendingPool(); -// const wethAddress = await getWethAddress(poolConfig); -// await deployUniswapWETHGateway([wethAddress, lendingPoolAddress]); -// }); diff --git a/tasks/full/1_address_provider.ts b/tasks/full/1_address_provider.ts index 94506c27..7c0ed167 100644 --- a/tasks/full/1_address_provider.ts +++ b/tasks/full/1_address_provider.ts @@ -81,7 +81,7 @@ task( // 2. Deploy address provider and set genesis manager const addressesProvider = await deployLendingPoolAddressesProvider(MarketId, verify); - // TEMPORARILY DISABLING SEC. 3 FOR KOVAN DEPLOYMENT + // TEMPORARILY DISABLING SEC. 3 FOR GOVERNANCE USE // 3. Set the provider at the Registry // await waitForTx( diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index 093ea43c..b064328f 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -1,5 +1,5 @@ import { task } from 'hardhat/config'; -import { getParamPerNetwork, getParamPerPool } from '../../helpers/contracts-helpers'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { deployAaveOracle, deployLendingRateOracle } from '../../helpers/contracts-deployments'; import { setInitialMarketRatesInRatesOracleByHelper } from '../../helpers/oracles-helpers'; import { ICommonConfiguration, eEthereumNetwork, SymbolMap } from '../../helpers/types'; @@ -32,8 +32,6 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') FallbackOracle, ChainlinkAggregator, } = poolConfig as ICommonConfiguration; - - //console.log("------------------------------------------------ReserveAssets:\n", ReserveAssets); const lendingRateOracles = getLendingRateOracles(poolConfig); const addressesProvider = await getLendingPoolAddressesProvider(); const admin = await getGenesisPoolAdmin(poolConfig); @@ -42,14 +40,13 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') const fallbackOracleAddress = await getParamPerNetwork(FallbackOracle, network); const reserveAssets = await getParamPerNetwork(ReserveAssets, network); const chainlinkAggregators = await getParamPerNetwork(ChainlinkAggregator, network); - //console.log("------------------------------------------------reserveAssets:\n", reserveAssets); const tokensToWatch: SymbolMap = { ...reserveAssets, USD: UsdAddress, }; const [tokens, aggregators] = getPairsTokenAggregator(tokensToWatch, chainlinkAggregators); - console.log("tokens:\n %s \n aggregators: \n %s", tokens, aggregators); + const aaveOracle = notFalsyOrZeroAddress(aaveOracleAddress) ? await getAaveOracle(aaveOracleAddress) : await deployAaveOracle( diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 77672bdc..444f55d8 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -36,7 +36,6 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const testHelpers = await getAaveProtocolDataProvider(); - console.log("reserveAssets:\n", reserveAssets); const admin = await addressesProvider.getPoolAdmin(); if (!reserveAssets) { throw 'Reserve assets is undefined. Check ReserveAssets configuration at config directory'; @@ -44,8 +43,8 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const treasuryAddress = await getTreasuryAddress(poolConfig); - await initReservesByHelper(addressesProvider, ReservesConfig, reserveAssets, admin, treasuryAddress, ZERO_ADDRESS, verify); - await configureReservesByHelper(addressesProvider, ReservesConfig, reserveAssets, testHelpers, admin); + await initReservesByHelper(ReservesConfig, reserveAssets, admin, treasuryAddress, ZERO_ADDRESS, verify); + await configureReservesByHelper(ReservesConfig, reserveAssets, testHelpers, admin); const collateralManager = await deployLendingPoolCollateralManager(verify); await waitForTx( diff --git a/tasks/migrations/aave.dev.ts b/tasks/migrations/aave.dev.ts index ed208c6b..1892cb53 100644 --- a/tasks/migrations/aave.dev.ts +++ b/tasks/migrations/aave.dev.ts @@ -20,24 +20,18 @@ task('aave:dev', 'Deploy development enviroment') console.log('1. Deploy mock tokens'); await localBRE.run('dev:deploy-mock-tokens', {verify}); - console.log('2. Deploy Aave market address provider'); + console.log('2. Deploy address provider'); await localBRE.run('dev:deploy-address-provider', {verify}); - console.log('3. Deploy Aave lending pool'); + console.log('3. Deploy lending pool'); await localBRE.run('dev:deploy-lending-pool', {verify}); console.log('4. Deploy oracles'); await localBRE.run('dev:deploy-oracles', {verify, pool: POOL_NAME}); - console.log('6. Deploy Uniswap market oracles'); - await localBRE.run('dev:deploy-oracles', {verify, pool: "Uniswap"}); - console.log('5. Initialize lending pool'); await localBRE.run('dev:initialize-lending-pool', {verify, pool: POOL_NAME}); - // console.log('6. Deploy Uniswap market'); - // await localBRE.run('dev:deploy-uniswap-market', {verify}); - console.log('\nFinished migration'); printContracts(); }); diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index e464b47f..7d2bb638 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -97,7 +97,6 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const addressList = await Promise.all( (await DRE.ethers.getSigners()).map((signer) => signer.getAddress()) ); - console.log(addressList); await waitForTx(await addressesProvider.setEmergencyAdmin(addressList[2])); @@ -216,9 +215,8 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const treasuryAddress = await getTreasuryAddress(config); - await initReservesByHelper(addressesProvider, reservesParams, allReservesAddresses, admin, treasuryAddress, ZERO_ADDRESS, false); + await initReservesByHelper(reservesParams, allReservesAddresses, admin, treasuryAddress, ZERO_ADDRESS, false); await configureReservesByHelper( - addressesProvider, reservesParams, allReservesAddresses, testHelpers, diff --git a/test/test b/test/test deleted file mode 100644 index 6b201f6c..00000000 --- a/test/test +++ /dev/null @@ -1,153 +0,0 @@ -N# Contracts: 152 -MintableERC20: 0xB00cC45B4a7d3e1FEE684cFc4417998A1c183e6d -LendingPoolAddressesProvider: 0x0459c841b02Aee8730730C737582c53B20a27288 -LendingPoolAddressesProviderRegistry: 0x22474D350EC2dA53D717E30b96e9a2B7628Ede5b -ReserveLogic: 0x7fAeC7791277Ff512c41CA903c177B2Ed952dDAc -GenericLogic: 0x33958cC3535Fc328369EAC2B2Bebd120D67C7fa1 -ValidationLogic: 0x2cBbbBE1B75Ad7848F0844215816F551f429c64f -LendingPoolImpl: 0x8456161947DFc1fC159A0B26c025cD2b4bba0c3e -LendingPool: 0xbAc762e2000b6815268587b081Fd17aC25519aD5 -LendingPoolConfiguratorImpl: 0x5F6CaC05CDF893f029b29F44d368eAeD40e573B6 -LendingPoolConfigurator: 0x2C4603396dE2F08642354A3A102760827FfFe113 -StableAndVariableTokensHelper: 0xadcD6f616fCEEbEd731B2B3F01B8bd51A08b5CbD -ATokensAndRatesHelper: 0x603A373A1571783bD82b708C20a5A4b019BAB78F -DAI: 0x7c2C195CD6D34B8F845992d380aADB2730bB9C6F -AAVE: 0x8858eeB3DfffA017D4BCE9801D340D36Cf895CCf -TUSD: 0x0078371BDeDE8aAc7DeBfFf451B74c5EDB385Af7 -BAT: 0xf4e77E5Da47AC3125140c470c71cBca77B5c638c -WETHMocked: 0x09d728F76D543DB1925f7d1Fd8823e4e82700F99 -WETH: 0xf784709d2317D872237C4bC22f867d1BAe2913AB -USDC: 0x3619DbE27d7c1e7E91aA738697Ae7Bc5FC3eACA5 -USDT: 0x038B86d9d8FAFdd0a02ebd1A476432877b0107C8 -SUSD: 0x1A1FEe7EeD918BD762173e4dc5EfDB8a78C924A8 -ZRX: 0x500D1d6A4c7D8Ae28240b47c8FCde034D827fD5e -MKR: 0xc4905364b78a742ccce7B890A89514061E47068D -WBTC: 0xD6C850aeBFDC46D7F4c207e445cC0d6B0919BDBe -LINK: 0x8B5B7a6055E54a36fF574bbE40cf2eA68d5554b3 -KNC: 0xEcc0a6dbC0bb4D51E4F84A315a9e5B0438cAD4f0 -MANA: 0x20Ce94F404343aD2752A2D01b43fa407db9E0D00 -REN: 0x1d80315fac6aBd3EfeEbE97dEc44461ba7556160 -SNX: 0x2D8553F9ddA85A9B3259F6Bf26911364B85556F5 -BUSD: 0x52d3b94181f8654db2530b0fEe1B19173f519C52 -USD: 0xd15468525c35BDBC1eD8F2e09A00F8a173437f2f -YFI: 0x7e35Eaf7e8FBd7887ad538D4A38Df5BbD073814a -UNI: 0x5bcb88A0d20426e451332eE6C4324b0e663c50E0 -ENJ: 0x3521eF8AaB0323004A6dD8b03CE890F4Ea3A13f5 -WETHDAI: 0x53369fd4680FfE3DfF39Fc6DDa9CfbfD43daeA2E -WETHWBTC: 0xB00cC45B4a7d3e1FEE684cFc4417998A1c183e6d -PriceOracle: 0x06bA8d8af0dF898D0712DffFb0f862cC51AF45c2 -MockAggregator: 0xA0AB1cB92A4AF81f84dCd258155B5c25D247b54E -AaveOracle: 0xD662fb7FDC7526C79AA4417d2A4415416e057ec4 -LendingRateOracle: 0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89 -AaveProtocolDataProvider: 0xf45C720549136d5E2d6a5A2F12573A36E36C3411 -stableDebtAAVE: 0xe3C388495669b8624753a275675AEf9eCc8Eaaa4 -variableDebtAAVE: 0xbdA8106CA657E2bfe1a125f0D0DDE47bA85E92c8 -stableDebtBAT: 0xa8c48Fad16b34bc9BC1203f1784D36CDf61dfD9c -variableDebtBAT: 0x5A7dE46c8176AF8550Df2fEF14464c2cB3B0EE5e -aAAVE: 0x1433d6d0794262c09f19E64177c0dD69A0e4D648 -strategyAAVE: 0x329e6747250B326E5E8029154DFFfE93F4f27016 -aBAT: 0x1A2e1C9d403E9DD6Da5022a14590ec875fBb75ba -strategyBAT: 0x12d5da143C6f7d3322C9b32cdF3a6Cae390A5293 -stableDebtBUSD: 0x453697f5d829556a0373F2b835cF94242B078C9e -variableDebtBUSD: 0x03D049FCA4dE1DA80F9DDF4bf0008115c74C0Da2 -stableDebtDAI: 0x30dDD022BC4df9BB0e6ce94A5535F2137dEA3755 -variableDebtDAI: 0xbfC8B61A3e6eD07C092a74603CeCAe91254745D6 -aBUSD: 0x1BC353ae7758eff98129928631a2D17d69BAb5FA -strategyBUSD: 0x270176D7DB4ec8d2a16b90C78B424AAdbBcFE298 -aDAI: 0x6A61442dBCF10E7168FfcD850CDf7c91Cad3E666 -strategyDAI: 0xA9DD0c06755734f4327F405cd20897D79FaCcFAE -stableDebtENJ: 0x6C0A2d54B37d8Cd321a25328753077D43A387303 -variableDebtENJ: 0x1372E5e41E22BaB997aD453469F0DFB9569dB121 -stableDebtKNC: 0x9bF0208c881906fAC92112320425b403e08Fe44b -variableDebtKNC: 0x6028834D13a4eec68b289E125222e5e5e86a5503 -aENJ: 0x2108E7A4B53516883b60a40ae02600697c8065A2 -strategyENJ: 0x64980e3e653Fe43813A41b9C5AcDB394d7A7320F -aKNC: 0x0f22acabf1Aa485565693B671Fc68B0583f8FEB0 -strategyKNC: 0xC45DA1E746911C76E51CA28b8d8A876735797E3C -stableDebtLINK: 0x3E650a21eAACE6314E98569E8A37FDA1d4cfBE28 -variableDebtLINK: 0xA7430bFB0f7332B1456dCB770D593f1D35bc2B11 -stableDebtMANA: 0x8DB6b6aE3c096E84B9818545974d1577E37Bcb97 -variableDebtMANA: 0x945ea0cf8986724ec075bE09C503c822fF8Ebb75 -aLINK: 0x778c890b128CE3936b744F0c8d7290d1F161D888 -strategyLINK: 0xCD8C6429A2975Db9466fCEFf36020166930a11Cb -aMANA: 0x5fd9aE04361262868d5C33cA1545580fC509b34c -strategyMANA: 0x024CC36954EfDbB9CFdda80a5A8c05Bd8DdF0fc8 -stableDebtMKR: 0xd1bD598200b53FC352483dBe36d9d72C085011A4 -variableDebtMKR: 0x49b81af588031Ecc93E20355E9ADC2d720348347 -stableDebtREN: 0x7367fBfEA2643eCbc0816Cc87B91E82B3Eb307aF -variableDebtREN: 0xAD75a04e5B815558a7E6C84c030e857671875934 -aMKR: 0xbEf21bFD5164eA882d74df73BB0862226C3063E9 -strategyMKR: 0x27a99bef2aF3200c6B7a831C61eF692341C7acEe -aREN: 0xe807dCAB5d5e8c5701c089758aAd34869a4c92Ea -strategyREN: 0xD933d804Dcb597Ac8020623ac32CcE3d4cB81b2a -stableDebtSNX: 0x3F33fb4D89eC6Bd516dCa915A3d85F0374d099d5 -variableDebtSNX: 0xD27B891432c9036E9dC95bc4fE9b8FCb61FBa05e -stableDebtSUSD: 0xFe3C98C3daE2F7562f43D1bBD2021FE127Afec38 -variableDebtSUSD: 0x53070063F0fB13C51C0e2186C0130f29aBe5336b -aSNX: 0x96a8C36C19D2A96642F2738b8E0481f159488EaD -strategySNX: 0xa5eB1859FA97E38C0a4257Af0be9085b3B4B7996 -aSUSD: 0x948Bd60Cba5eB8b7A478aE673145FeA13e2Edbe8 -strategySUSD: 0x7C769501542E694a5Dea6B1FCAf52B9270EADcaf -stableDebtTUSD: 0x6c2E76485dFbaFe2FCC6874e531D71ee82db06f6 -variableDebtTUSD: 0x3FA01122234D545d0247bdDbf4865925A53f6551 -stableDebtUSDC: 0xDD7a535Fb8773EBc4Ae653eCCb22F6561F434a9E -variableDebtUSDC: 0x9d1718D33aE17e54D2aE329b6B51511d4371Bf4a -aTUSD: 0x802881960dCD9457F63c4dbe1E9D081b32b011b9 -strategyTUSD: 0xC1f335a47c45d9F15976A1e11Eb3826590AD2a56 -aUSDC: 0x1CC642F9b88f755C1E7fbB9Acb4A990faddBF608 -strategyUSDC: 0x4272DE39F41085769562b2c17Fd5369097E41492 -stableDebtUSDT: 0x372915a5Bed2B0a5ecEdc96e7133A24aDDFA4Bc4 -variableDebtUSDT: 0x78123523ba15F9847D22a6d3f06bBed70E431114 -stableDebtWBTC: 0x6a3aB96987B70E29bc4203f78D09D0aCB85F219D -variableDebtWBTC: 0xcDD6c3f0dA05129f08DB52380C48A9cf698A8CCA -aUSDT: 0xe88141a1642eD64AE739cd2C896009Be73a43486 -strategyUSDT: 0x881036687070243FC119014c41cdd5e3c22f3E50 -aWBTC: 0xE74801a99A51B89dE670132De7d9c18CC2BBE54A -strategyWBTC: 0x55DFA1D5af234B35D457C13B8a58899848A438F8 -stableDebtWETH: 0xD1220D8A82a26C1396cccb5Ee79d3A42D7D3E3da -variableDebtWETH: 0x4f87eBaac31C3d13C376d52A0FABf5f022660C4c -stableDebtYFI: 0xF2dB8bc0dCd0A6C6F25B7f6ACfB9E026ae0e7494 -variableDebtYFI: 0xce3529624a1f3Ea5DBC1AB130eBeA8211E3b602F -aWETH: 0x7e4b842FFc0598C1f5D8b8A1e2C7AD29E9F233C7 -strategyWETH: 0x52Ac4c1Dbc0263b2FD6AD065B27576d0E7d925B9 -aYFI: 0x895D60248de2edc34C99f1B45d8Dd1731656Df51 -strategyYFI: 0x3cE6D0B4b6dc27C725fA94903Fb33d73bE75e9D7 -stableDebtZRX: 0xF78Fbf3b21aF8Bce2efA3614E507735573c578CC -variableDebtZRX: 0x9Ae60ba71A28a1d738a2FDFC1D0439B33f3f0B1F -aZRX: 0x80aB7B8EfeA24C2D2Ca22315BFa99E03f539C568 -strategyZRX: 0x4D2271CFa5587643B8f5919f3EbF64de7aaa9d5c -DelegationAwareAToken: 0xBAdDA897176B5A94FD4A0eCb59678DDA29181963 -StableDebtToken: 0x64Ea58f488aD445235A0afE9256B066572c6Abc8 -VariableDebtToken: 0x8D0206fEBEB380486729b64bB4cfEDC5b354a6D6 -DefaultReserveInterestRateStrategy: 0x3c5408De7435Dfa3eB2aF2Edf5E39385f68F69b2 -LendingPoolCollateralManagerImpl: 0x6602fca48E95F5068506963E3A8930131108048A -LendingPoolCollateralManager: 0x6602fca48E95F5068506963E3A8930131108048A -MockFlashLoanReceiver: 0x1a66D6103F8BBf9204E1618F095a80b3E4817C95 -WalletBalanceProvider: 0x0EBCa695959e5f138Af772FAa44ce1A9C7aEd921 -WETHGateway: 0x8BFFF31B1757da579Bb5B118489568526F7fb6D4 -MintableDelegationERC20: 0x8BFFF31B1757da579Bb5B118489568526F7fb6D4 -MockAToken: 0x8BFFF31B1757da579Bb5B118489568526F7fb6D4 -MockStableDebtToken: 0x0459c841b02Aee8730730C737582c53B20a27288 -MockVariableDebtToken: 0x2530ce07D254eA185E8e0bCC37a39e2FbA3bE548 -SelfdestructTransferMock: 0x0459c841b02Aee8730730C737582c53B20a27288 -UniswapLendingPool: 0xEC42F4C314dE9492cb3Ef7a860270eCDFE0F851a -UniswapLendingPoolConfigurator: 0x672A68Ff1364E87D8f88ad86410449C117fC97A6 -UniswapLendingPoolAddressesProvider: 0x18b9306737eaf6E8FC8e737F488a1AE077b18053 -UniswapLendingPoolImpl: 0xbAc762e2000b6815268587b081Fd17aC25519aD5 -UniswapLendingPoolConfiguratorImpl: 0xAa7BC1924711B77A0F3Aaebdd550BfeDDDbaf3cd -UniswapPriceOracle: 0xFf130817Aa9863B3D809A2A11617c05646245d80 -UniswapAaveOracle: 0xE91bBe8ee03560E3dda2786f95335F5399813Ca0 -UniswapLendingRateOracle: 0x4977FC58783ceBCC310311C800B786EcAf45F98f -stableDebtWETHDAI: 0x84fF0147dDD2acA72407CfEB7EabCd2b7E49d949 -variableDebtWETHDAI: 0x35A1E1Be236899ab7B63a81127ab522d76A26B3e -aWETHDAI: 0x591D75Ea272E9F22fC4B20Fc4C4E03d8c126b1AB -strategyWETHDAI: 0xF4040B68C37eE6F1324470f48D05cCEC50819b2E -stableDebtWETHWBTC: 0x5a41efF010872DB9a2CA0b47b8b757f37dc35A7f -variableDebtWETHWBTC: 0xee0382a3E9ADeAaA670c425D51ad5F8022c6d9F8 -aWETHWBTC: 0x4dA415c7aDaC37c3d710B5D24b62c6f4a5aF6e5F -strategyWETHWBTC: 0xf0c3F1cd72eA0a1F4e0e98B2e0702fA63a9F9faF -UniswapLendingPoolCollateralManagerImpl: 0x9D2F6Ec881323E78f27d58b996b81EaBCEF8eC58 -UniswapLendingPoolCollateralManager: 0x9D2F6Ec881323E78f27d58b996b81EaBCEF8eC58 -UniswapMockFlashLoanReceiver: 0xad17D0b25259128C968dbCa61CB5864C78004DBE -UniswapWalletBalanceProvider: 0x6Ac05758229c725A6d14F0ae7088985D9B251Fb2 -UniswapWETHGateway: 0xb2B548BE73010C188C083c510d255Aed74843b05 \ No newline at end of file From a4540633eaec9112d4b4319044c29c4b8f655746 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Sun, 10 Jan 2021 20:41:58 -0500 Subject: [PATCH 014/219] Removed obsolete note --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index d5d9b6bc..ae2e7b69 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -### Uniswap V2 Liquidity Pool Market Aave Fork ``` .///. .///. //. .// `/////////////- `++:++` .++:++` :++` `++: `++:......---.` From b432008d06a41b321d4b7c87c34ad40332f99cc0 Mon Sep 17 00:00:00 2001 From: David Racero Date: Mon, 11 Jan 2021 17:40:25 +0100 Subject: [PATCH 015/219] Added flash liquidation adapter first iteration --- contracts/adapters/BaseUniswapAdapter.sol | 545 ++++++++++++++++++ .../adapters/FlashLiquidationAdapter.sol | 254 ++++++++ .../interfaces/IBaseUniswapAdapter.sol | 92 +++ contracts/interfaces/IERC20WithPermit.sol | 16 + contracts/interfaces/IUniswapV2Router02.sol | 30 + 5 files changed, 937 insertions(+) create mode 100644 contracts/adapters/BaseUniswapAdapter.sol create mode 100644 contracts/adapters/FlashLiquidationAdapter.sol create mode 100644 contracts/adapters/interfaces/IBaseUniswapAdapter.sol create mode 100644 contracts/interfaces/IERC20WithPermit.sol create mode 100644 contracts/interfaces/IUniswapV2Router02.sol diff --git a/contracts/adapters/BaseUniswapAdapter.sol b/contracts/adapters/BaseUniswapAdapter.sol new file mode 100644 index 00000000..67c0a3d5 --- /dev/null +++ b/contracts/adapters/BaseUniswapAdapter.sol @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {PercentageMath} from '../protocol/libraries/math/PercentageMath.sol'; +import {SafeMath} from '../dependencies/openzeppelin/contracts/SafeMath.sol'; +import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; +import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; +import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol'; +import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol'; +import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; +import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; +import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol'; +import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol'; +import {IERC20WithPermit} from '../interfaces/IERC20WithPermit.sol'; +import {FlashLoanReceiverBase} from '../flashloan/base/FlashLoanReceiverBase.sol'; +import {IBaseUniswapAdapter} from './interfaces/IBaseUniswapAdapter.sol'; + +/** + * @title BaseUniswapAdapter + * @notice Implements the logic for performing assets swaps in Uniswap V2 + * @author Aave + **/ +abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapter, Ownable { + using SafeMath for uint256; + using PercentageMath for uint256; + using SafeERC20 for IERC20; + + // Max slippage percent allowed + uint256 public constant override MAX_SLIPPAGE_PERCENT = 3000; // 30% + // FLash Loan fee set in lending pool + uint256 public constant override FLASHLOAN_PREMIUM_TOTAL = 9; + // USD oracle asset address + address public constant override USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96; + + // address public constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; mainnet + // address public constant WETH_ADDRESS = 0xd0a1e359811322d97991e03f863a0c30c2cf029c; kovan + + address public immutable override WETH_ADDRESS; + IPriceOracleGetter public immutable override ORACLE; + IUniswapV2Router02 public immutable override UNISWAP_ROUTER; + + constructor( + ILendingPoolAddressesProvider addressesProvider, + IUniswapV2Router02 uniswapRouter, + address wethAddress + ) public FlashLoanReceiverBase(addressesProvider) { + ORACLE = IPriceOracleGetter(addressesProvider.getPriceOracle()); + UNISWAP_ROUTER = uniswapRouter; + WETH_ADDRESS = wethAddress; + } + + /** + * @dev Given an input asset amount, returns the maximum output amount of the other asset and the prices + * @param amountIn Amount of reserveIn + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @return uint256 Amount out of the reserveOut + * @return uint256 The price of out amount denominated in the reserveIn currency (18 decimals) + * @return uint256 In amount of reserveIn value denominated in USD (8 decimals) + * @return uint256 Out amount of reserveOut value denominated in USD (8 decimals) + */ + function getAmountsOut( + uint256 amountIn, + address reserveIn, + address reserveOut, + bool withFlash + ) + external + view + override + returns ( + uint256, + uint256, + uint256, + uint256, + address[] memory + ) + { + AmountCalc memory results = _getAmountsOutData(reserveIn, reserveOut, amountIn, withFlash); + + return ( + results.calculatedAmount, + results.relativePrice, + results.amountInUsd, + results.amountOutUsd, + results.path + ); + } + + /** + * @dev Returns the minimum input asset amount required to buy the given output asset amount and the prices + * @param amountOut Amount of reserveOut + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @return uint256 Amount in of the reserveIn + * @return uint256 The price of in amount denominated in the reserveOut currency (18 decimals) + * @return uint256 In amount of reserveIn value denominated in USD (8 decimals) + * @return uint256 Out amount of reserveOut value denominated in USD (8 decimals) + */ + function getAmountsIn( + uint256 amountOut, + address reserveIn, + address reserveOut, + bool withFlash + ) + external + view + override + returns ( + uint256, + uint256, + uint256, + uint256, + address[] memory + ) + { + AmountCalc memory results = _getAmountsInData(reserveIn, reserveOut, amountOut, withFlash); + + return ( + results.calculatedAmount, + results.relativePrice, + results.amountInUsd, + results.amountOutUsd, + results.path + ); + } + + /** + * @dev Swaps an exact `amountToSwap` of an asset to another + * @param assetToSwapFrom Origin asset + * @param assetToSwapTo Destination asset + * @param amountToSwap Exact amount of `assetToSwapFrom` to be swapped + * @param minAmountOut the min amount of `assetToSwapTo` to be received from the swap + * @return the amount received from the swap + */ + function _swapExactTokensForTokens( + address assetToSwapFrom, + address assetToSwapTo, + uint256 amountToSwap, + uint256 minAmountOut, + bool useEthPath + ) internal returns (uint256) { + uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom); + uint256 toAssetDecimals = _getDecimals(assetToSwapTo); + + uint256 fromAssetPrice = _getPrice(assetToSwapFrom); + uint256 toAssetPrice = _getPrice(assetToSwapTo); + + uint256 expectedMinAmountOut = + amountToSwap + .mul(fromAssetPrice.mul(10**toAssetDecimals)) + .div(toAssetPrice.mul(10**fromAssetDecimals)) + .percentMul(PercentageMath.PERCENTAGE_FACTOR.sub(MAX_SLIPPAGE_PERCENT)); + + require(expectedMinAmountOut < minAmountOut, 'minAmountOut exceed max slippage'); + + IERC20(assetToSwapFrom).approve(address(UNISWAP_ROUTER), amountToSwap); + + address[] memory path; + if (useEthPath) { + path = new address[](3); + path[0] = assetToSwapFrom; + path[1] = WETH_ADDRESS; + path[2] = assetToSwapTo; + } else { + path = new address[](2); + path[0] = assetToSwapFrom; + path[1] = assetToSwapTo; + } + uint256[] memory amounts = + UNISWAP_ROUTER.swapExactTokensForTokens( + amountToSwap, + minAmountOut, + path, + address(this), + block.timestamp + ); + + emit Swapped(assetToSwapFrom, assetToSwapTo, amounts[0], amounts[amounts.length - 1]); + + return amounts[amounts.length - 1]; + } + + /** + * @dev Receive an exact amount `amountToReceive` of `assetToSwapTo` tokens for as few `assetToSwapFrom` tokens as + * possible. + * @param assetToSwapFrom Origin asset + * @param assetToSwapTo Destination asset + * @param maxAmountToSwap Max amount of `assetToSwapFrom` allowed to be swapped + * @param amountToReceive Exact amount of `assetToSwapTo` to receive + * @return the amount swapped + */ + function _swapTokensForExactTokens( + address assetToSwapFrom, + address assetToSwapTo, + uint256 maxAmountToSwap, + uint256 amountToReceive, + bool useEthPath + ) internal returns (uint256) { + address[] memory path; + uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom); + uint256 toAssetDecimals = _getDecimals(assetToSwapTo); + + uint256 fromAssetPrice = _getPrice(assetToSwapFrom); + uint256 toAssetPrice = _getPrice(assetToSwapTo); + + uint256 expectedMaxAmountToSwap = + amountToReceive + .mul(toAssetPrice.mul(10**fromAssetDecimals)) + .div(fromAssetPrice.mul(10**toAssetDecimals)) + .percentMul(PercentageMath.PERCENTAGE_FACTOR.add(MAX_SLIPPAGE_PERCENT)); + + require(maxAmountToSwap < expectedMaxAmountToSwap, 'maxAmountToSwap exceed max slippage'); + + IERC20(assetToSwapFrom).approve(address(UNISWAP_ROUTER), maxAmountToSwap); + + if (useEthPath) { + path = new address[](3); + path[0] = assetToSwapFrom; + path[1] = WETH_ADDRESS; + path[2] = assetToSwapTo; + } else { + path = new address[](2); + path[0] = assetToSwapFrom; + path[1] = assetToSwapTo; + } + uint256[] memory amounts = + UNISWAP_ROUTER.swapTokensForExactTokens( + amountToReceive, + maxAmountToSwap, + path, + address(this), + block.timestamp + ); + + emit Swapped(assetToSwapFrom, assetToSwapTo, amounts[0], amounts[amounts.length - 1]); + + return amounts[0]; + } + + /** + * @dev Get the price of the asset from the oracle denominated in eth + * @param asset address + * @return eth price for the asset + */ + function _getPrice(address asset) internal view returns (uint256) { + return ORACLE.getAssetPrice(asset); + } + + /** + * @dev Get the decimals of an asset + * @return number of decimals of the asset + */ + function _getDecimals(address asset) internal view returns (uint256) { + return IERC20Detailed(asset).decimals(); + } + + /** + * @dev Get the aToken associated to the asset + * @return address of the aToken + */ + function _getReserveData(address asset) internal view returns (DataTypes.ReserveData memory) { + return LENDING_POOL.getReserveData(asset); + } + + /** + * @dev Pull the ATokens from the user + * @param reserve address of the asset + * @param reserveAToken address of the aToken of the reserve + * @param user address + * @param amount of tokens to be transferred to the contract + * @param permitSignature struct containing the permit signature + */ + function _pullAToken( + address reserve, + address reserveAToken, + address user, + uint256 amount, + PermitSignature memory permitSignature + ) internal { + if (_usePermit(permitSignature)) { + IERC20WithPermit(reserveAToken).permit( + user, + address(this), + permitSignature.amount, + permitSignature.deadline, + permitSignature.v, + permitSignature.r, + permitSignature.s + ); + } + + // transfer from user to adapter + IERC20(reserveAToken).safeTransferFrom(user, address(this), amount); + + // withdraw reserve + LENDING_POOL.withdraw(reserve, amount, address(this)); + } + + /** + * @dev Tells if the permit method should be called by inspecting if there is a valid signature. + * If signature params are set to 0, then permit won't be called. + * @param signature struct containing the permit signature + * @return whether or not permit should be called + */ + function _usePermit(PermitSignature memory signature) internal pure returns (bool) { + return + !(uint256(signature.deadline) == uint256(signature.v) && uint256(signature.deadline) == 0); + } + + /** + * @dev Calculates the value denominated in USD + * @param reserve Address of the reserve + * @param amount Amount of the reserve + * @param decimals Decimals of the reserve + * @return whether or not permit should be called + */ + function _calcUsdValue( + address reserve, + uint256 amount, + uint256 decimals + ) internal view returns (uint256) { + uint256 ethUsdPrice = _getPrice(USD_ADDRESS); + uint256 reservePrice = _getPrice(reserve); + + return amount.mul(reservePrice).div(10**decimals).mul(ethUsdPrice).div(10**18); + } + + struct AmountOutVars { + uint256 finalAmountIn; + address[] simplePath; + uint256[] amountsWithoutWeth; + uint256[] amountsWithWeth; + address[] pathWithWeth; + } + + /** + * @dev Given an input asset amount, returns the maximum output amount of the other asset + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @param amountIn Amount of reserveIn + * @return Struct containing the following information: + * uint256 Amount out of the reserveOut + * uint256 The price of out amount denominated in the reserveIn currency (18 decimals) + * uint256 In amount of reserveIn value denominated in USD (8 decimals) + * uint256 Out amount of reserveOut value denominated in USD (8 decimals) + */ + function _getAmountsOutData( + address reserveIn, + address reserveOut, + uint256 amountIn, + bool withFlash + ) internal view returns (AmountCalc memory) { + AmountOutVars memory vars; + // Subtract flash loan fee + vars.finalAmountIn = amountIn.sub( + withFlash ? amountIn.mul(FLASHLOAN_PREMIUM_TOTAL).div(10000) : 0 + ); + + vars.simplePath = new address[](2); + vars.simplePath[0] = reserveIn; + vars.simplePath[1] = reserveOut; + + vars.pathWithWeth = new address[](3); + if (reserveIn != WETH_ADDRESS && reserveOut != WETH_ADDRESS) { + vars.pathWithWeth[0] = reserveIn; + vars.pathWithWeth[1] = WETH_ADDRESS; + vars.pathWithWeth[2] = reserveOut; + + try UNISWAP_ROUTER.getAmountsOut(vars.finalAmountIn, vars.pathWithWeth) returns ( + uint256[] memory resultsWithWeth + ) { + vars.amountsWithWeth = resultsWithWeth; + } catch { + vars.amountsWithWeth = new uint256[](3); + } + } else { + vars.amountsWithWeth = new uint256[](3); + } + + uint256 bestAmountOut; + try UNISWAP_ROUTER.getAmountsOut(vars.finalAmountIn, vars.simplePath) returns ( + uint256[] memory resultAmounts + ) { + vars.amountsWithoutWeth = resultAmounts; + + bestAmountOut = (vars.amountsWithWeth[2] > vars.amountsWithoutWeth[1]) + ? vars.amountsWithWeth[2] + : vars.amountsWithoutWeth[1]; + } catch { + vars.amountsWithoutWeth = new uint256[](2); + bestAmountOut = vars.amountsWithWeth[2]; + } + + uint256 reserveInDecimals = _getDecimals(reserveIn); + uint256 reserveOutDecimals = _getDecimals(reserveOut); + + uint256 outPerInPrice = + vars.finalAmountIn.mul(10**18).mul(10**reserveOutDecimals).div( + bestAmountOut.mul(10**reserveInDecimals) + ); + + return + AmountCalc( + bestAmountOut, + outPerInPrice, + _calcUsdValue(reserveIn, amountIn, reserveInDecimals), + _calcUsdValue(reserveOut, bestAmountOut, reserveOutDecimals), + (bestAmountOut == 0) ? new address[](2) : (bestAmountOut == vars.amountsWithoutWeth[1]) + ? vars.simplePath + : vars.pathWithWeth + ); + } + + /** + * @dev Returns the minimum input asset amount required to buy the given output asset amount + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @param amountOut Amount of reserveOut + * @return Struct containing the following information: + * uint256 Amount in of the reserveIn + * uint256 The price of in amount denominated in the reserveOut currency (18 decimals) + * uint256 In amount of reserveIn value denominated in USD (8 decimals) + * uint256 Out amount of reserveOut value denominated in USD (8 decimals) + */ + function _getAmountsInData( + address reserveIn, + address reserveOut, + uint256 amountOut, + bool withFlash + ) internal view returns (AmountCalc memory) { + (uint256[] memory amounts, address[] memory path) = + _getAmountsInAndPath(reserveIn, reserveOut, amountOut); + + // Add flash loan fee + uint256 finalAmountIn = + amounts[0].add(withFlash ? amounts[0].mul(FLASHLOAN_PREMIUM_TOTAL).div(10000) : 0); + + uint256 reserveInDecimals = _getDecimals(reserveIn); + uint256 reserveOutDecimals = _getDecimals(reserveOut); + + uint256 inPerOutPrice = + amountOut.mul(10**18).mul(10**reserveInDecimals).div( + finalAmountIn.mul(10**reserveOutDecimals) + ); + + return + AmountCalc( + finalAmountIn, + inPerOutPrice, + _calcUsdValue(reserveIn, finalAmountIn, reserveInDecimals), + _calcUsdValue(reserveOut, amountOut, reserveOutDecimals), + path + ); + } + + /** + * @dev Calculates the input asset amount required to buy the given output asset amount + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @param amountOut Amount of reserveOut + * @return uint256[] amounts Array containing the amountIn and amountOut for a swap + */ + function _getAmountsInAndPath( + address reserveIn, + address reserveOut, + uint256 amountOut + ) internal view returns (uint256[] memory, address[] memory) { + address[] memory simplePath = new address[](2); + simplePath[0] = reserveIn; + simplePath[1] = reserveOut; + + uint256[] memory amountsWithoutWeth; + uint256[] memory amountsWithWeth; + address[] memory pathWithWeth = new address[](3); + + if (reserveIn != WETH_ADDRESS && reserveOut != WETH_ADDRESS) { + pathWithWeth[0] = reserveIn; + pathWithWeth[1] = WETH_ADDRESS; + pathWithWeth[2] = reserveOut; + + try UNISWAP_ROUTER.getAmountsIn(amountOut, pathWithWeth) returns ( + uint256[] memory resultsWithWeth + ) { + amountsWithWeth = resultsWithWeth; + } catch { + amountsWithWeth = new uint256[](3); + } + } else { + amountsWithWeth = new uint256[](3); + } + + try UNISWAP_ROUTER.getAmountsIn(amountOut, simplePath) returns ( + uint256[] memory resultAmounts + ) { + amountsWithoutWeth = resultAmounts; + + return + (amountsWithWeth[2] > amountsWithoutWeth[1]) + ? (amountsWithWeth, pathWithWeth) + : (amountsWithoutWeth, simplePath); + } catch { + return (amountsWithWeth, pathWithWeth); + } + } + + /** + * @dev Calculates the input asset amount required to buy the given output asset amount + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @param amountOut Amount of reserveOut + * @return uint256[] amounts Array containing the amountIn and amountOut for a swap + */ + function _getAmountsIn( + address reserveIn, + address reserveOut, + uint256 amountOut, + bool useEthPath + ) internal view returns (uint256[] memory) { + address[] memory path; + + if (useEthPath) { + path = new address[](3); + path[0] = reserveIn; + path[1] = WETH_ADDRESS; + path[2] = reserveOut; + } else { + path = new address[](2); + path[0] = reserveIn; + path[1] = reserveOut; + } + + return UNISWAP_ROUTER.getAmountsIn(amountOut, path); + } + + /** + * @dev Emergency rescue for token stucked on this contract, as failsafe mechanism + * - Funds should never remain in this contract more time than during transactions + * - Only callable by the owner + **/ + function rescueTokens(IERC20 token) external onlyOwner { + token.transfer(owner(), token.balanceOf(address(this))); + } +} diff --git a/contracts/adapters/FlashLiquidationAdapter.sol b/contracts/adapters/FlashLiquidationAdapter.sol new file mode 100644 index 00000000..4b07de60 --- /dev/null +++ b/contracts/adapters/FlashLiquidationAdapter.sol @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {BaseUniswapAdapter} from './BaseUniswapAdapter.sol'; +import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; +import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol'; +import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; +import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; +import {Helpers} from '../protocol/libraries/helpers/Helpers.sol'; +import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol'; +import {IAToken} from '../interfaces/IAToken.sol'; +import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol'; + +/** + * @title UniswapLiquiditySwapAdapter + * @notice Uniswap V2 Adapter to swap liquidity. + * @author Aave + **/ +contract FlashLiquidationAdapter is BaseUniswapAdapter { + using ReserveConfiguration for DataTypes.ReserveConfigurationMap; + uint256 internal constant LIQUIDATION_CLOSE_FACTOR_PERCENT = 5000; + + struct LiquidationParams { + address collateralAsset; + address debtAsset; + address user; + uint256 debtToCover; + bool useEthPath; + } + + struct LiquidationCallLocalVars { + uint256 userCollateralBalance; + uint256 userStableDebt; + uint256 userVariableDebt; + uint256 maxLiquidatableDebt; + uint256 actualDebtToLiquidate; + uint256 maxAmountCollateralToLiquidate; + uint256 maxCollateralToLiquidate; + uint256 debtAmountNeeded; + uint256 collateralPrice; + uint256 debtAssetPrice; + uint256 liquidationBonus; + uint256 collateralDecimals; + uint256 debtAssetDecimals; + IAToken collateralAtoken; + } + + constructor( + ILendingPoolAddressesProvider addressesProvider, + IUniswapV2Router02 uniswapRouter, + address wethAddress + ) public BaseUniswapAdapter(addressesProvider, uniswapRouter, wethAddress) {} + + /** + * @dev Liquidate a non-healthy position collateral-wise, with a Health Factor below 1, using Flash Loan and Uniswap to repay flash loan premium. + * - The caller (liquidator) with a flash loan covers `debtToCover` amount of debt of the user getting liquidated, and receives + * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk minus the flash loan premium. + * @param assets Address of asset to be swapped + * @param amounts Amount of the asset to be swapped + * @param premiums Fee of the flash loan + * @param initiator Address of the caller + * @param params Additional variadic field to include extra params. Expected parameters: + * address collateralAsset The collateral asset to release and will be exchanged to pay the flash loan premium + * address debtAsset The asset that must be covered + * address user The user address with a Health Factor below 1 + * uint256 debtToCover The amount of debt to cover + * bool useEthPath Use WETH as connector path between the collateralAsset and debtAsset at Uniswap + */ + function executeOperation( + address[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata premiums, + address initiator, + bytes calldata params + ) external override returns (bool) { + require(msg.sender == address(LENDING_POOL), 'CALLER_MUST_BE_LENDING_POOL'); + + LiquidationParams memory decodedParams = _decodeParams(params); + + require(assets.length == 1 && assets[0] == decodedParams.debtAsset, 'INCONSISTENT_PARAMS'); + + _liquidateAndSwap( + decodedParams.collateralAsset, + decodedParams.debtAsset, + decodedParams.user, + decodedParams.debtToCover, + decodedParams.useEthPath, + amounts[0], + premiums[0], + initiator + ); + + return true; + } + + /** + * @dev + * @param collateralAsset The collateral asset to release and will be exchanged to pay the flash loan premium + * @param debtAsset The asset that must be covered + * @param user The user address with a Health Factor below 1 + * @param debtToCover The amount of debt to coverage, can be max(-1) to liquidate all possible debt + * @param useEthPath true if the swap needs to occur using ETH in the routing, false otherwise + * @param coverAmount Amount of asset requested at the flash loan to liquidate the user position + * @param premium Fee of the requested flash loan + * @param initiator Address of the caller + */ + function _liquidateAndSwap( + address collateralAsset, + address debtAsset, + address user, + uint256 debtToCover, + bool useEthPath, + uint256 coverAmount, + uint256 premium, + address initiator + ) internal { + DataTypes.ReserveData memory collateralReserve = LENDING_POOL.getReserveData(collateralAsset); + DataTypes.ReserveData memory debtReserve = LENDING_POOL.getReserveData(debtAsset); + LiquidationCallLocalVars memory vars; + + (vars.userStableDebt, vars.userVariableDebt) = Helpers.getUserCurrentDebtMemory( + user, + debtReserve + ); + + vars.maxLiquidatableDebt = vars.userStableDebt.add(vars.userVariableDebt).percentMul( + LIQUIDATION_CLOSE_FACTOR_PERCENT + ); + vars.userCollateralBalance = vars.collateralAtoken.balanceOf(user); + vars.actualDebtToLiquidate = debtToCover > vars.maxLiquidatableDebt + ? vars.maxLiquidatableDebt + : debtToCover; + + ( + vars.maxCollateralToLiquidate, + vars.debtAmountNeeded + ) = _calculateAvailableCollateralToLiquidate( + collateralReserve, + debtReserve, + collateralAsset, + debtAsset, + vars.actualDebtToLiquidate, + vars.userCollateralBalance + ); + + require(coverAmount >= vars.debtAmountNeeded, 'Not enought cover amount requested'); + + uint256 flashLoanDebt = coverAmount.add(premium); + + // Liquidate the user position and release the underlying collateral + LENDING_POOL.liquidationCall(collateralAsset, debtAsset, user, debtToCover, false); + + // Swap released collateral into the debt asset, to repay the flash loan + uint256 soldAmount = + _swapTokensForExactTokens( + collateralAsset, + debtAsset, + vars.maxCollateralToLiquidate, + flashLoanDebt, + useEthPath + ); + + // Repay flash loan + IERC20(debtAsset).approve(address(LENDING_POOL), flashLoanDebt); + + // Transfer remaining profit to initiator + if (vars.maxCollateralToLiquidate.sub(soldAmount) > 0) { + IERC20(collateralAsset).transfer(initiator, vars.maxCollateralToLiquidate.sub(soldAmount)); + } + } + + /** + * @dev Decodes the information encoded in the flash loan params + * @param params Additional variadic field to include extra params. Expected parameters: + * address collateralAsset The collateral asset to claim + * address debtAsset The asset that must be covered and will be exchanged to pay the flash loan premium + * address user The user address with a Health Factor below 1 + * uint256 debtToCover The amount of debt to cover + * bool useEthPath Use WETH as connector path between the collateralAsset and debtAsset at Uniswap + * @return LiquidationParams struct containing decoded params + */ + function _decodeParams(bytes memory params) internal pure returns (LiquidationParams memory) { + ( + address collateralAsset, + address debtAsset, + address user, + uint256 debtToCover, + bool useEthPath + ) = abi.decode(params, (address, address, address, uint256, bool)); + + return LiquidationParams(collateralAsset, debtAsset, user, debtToCover, useEthPath); + } + + /** + * @dev Calculates how much of a specific collateral can be liquidated, given + * a certain amount of debt asset. + * - This function needs to be called after all the checks to validate the liquidation have been performed, + * otherwise it might fail. + * @param collateralReserve The data of the collateral reserve + * @param debtReserve The data of the debt reserve + * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation + * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation + * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover + * @param userCollateralBalance The collateral balance for the specific `collateralAsset` of the user being liquidated + * @return collateralAmount: The maximum amount that is possible to liquidate given all the liquidation constraints + * (user balance, close factor) + * debtAmountNeeded: The amount to repay with the liquidation + **/ + function _calculateAvailableCollateralToLiquidate( + DataTypes.ReserveData memory collateralReserve, + DataTypes.ReserveData memory debtReserve, + address collateralAsset, + address debtAsset, + uint256 debtToCover, + uint256 userCollateralBalance + ) internal view returns (uint256, uint256) { + uint256 collateralAmount = 0; + uint256 debtAmountNeeded = 0; + + LiquidationCallLocalVars memory vars; + + vars.collateralPrice = ORACLE.getAssetPrice(collateralAsset); + vars.debtAssetPrice = ORACLE.getAssetPrice(debtAsset); + + (, , vars.liquidationBonus, vars.collateralDecimals, ) = collateralReserve + .configuration + .getParamsMemory(); + (, , , , vars.debtAssetDecimals) = debtReserve.configuration.getParamsMemory(); + + // This is the maximum possible amount of the selected collateral that can be liquidated, given the + // max amount of liquidatable debt + vars.maxAmountCollateralToLiquidate = vars + .debtAssetPrice + .mul(debtToCover) + .mul(10**vars.collateralDecimals) + .percentMul(vars.liquidationBonus) + .div(vars.collateralPrice.mul(10**vars.debtAssetDecimals)); + + if (vars.maxAmountCollateralToLiquidate > userCollateralBalance) { + collateralAmount = userCollateralBalance; + debtAmountNeeded = vars + .collateralPrice + .mul(collateralAmount) + .mul(10**vars.debtAssetDecimals) + .div(vars.debtAssetPrice.mul(10**vars.collateralDecimals)) + .percentDiv(vars.liquidationBonus); + } else { + collateralAmount = vars.maxAmountCollateralToLiquidate; + debtAmountNeeded = debtToCover; + } + return (collateralAmount, debtAmountNeeded); + } +} diff --git a/contracts/adapters/interfaces/IBaseUniswapAdapter.sol b/contracts/adapters/interfaces/IBaseUniswapAdapter.sol new file mode 100644 index 00000000..e94727a2 --- /dev/null +++ b/contracts/adapters/interfaces/IBaseUniswapAdapter.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol'; +import {IUniswapV2Router02} from '../../interfaces/IUniswapV2Router02.sol'; + +interface IBaseUniswapAdapter { + event Swapped(address fromAsset, address toAsset, uint256 fromAmount, uint256 receivedAmount); + + struct PermitSignature { + uint256 amount; + uint256 deadline; + uint8 v; + bytes32 r; + bytes32 s; + } + + struct AmountCalc { + uint256 calculatedAmount; + uint256 relativePrice; + uint256 amountInUsd; + uint256 amountOutUsd; + address[] path; + } + + function WETH_ADDRESS() external returns (address); + + function MAX_SLIPPAGE_PERCENT() external returns (uint256); + + function FLASHLOAN_PREMIUM_TOTAL() external returns (uint256); + + function USD_ADDRESS() external returns (address); + + function ORACLE() external returns (IPriceOracleGetter); + + function UNISWAP_ROUTER() external returns (IUniswapV2Router02); + + /** + * @dev Given an input asset amount, returns the maximum output amount of the other asset and the prices + * @param amountIn Amount of reserveIn + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @return uint256 Amount out of the reserveOut + * @return uint256 The price of out amount denominated in the reserveIn currency (18 decimals) + * @return uint256 In amount of reserveIn value denominated in USD (8 decimals) + * @return uint256 Out amount of reserveOut value denominated in USD (8 decimals) + * @return address[] The exchange path + */ + function getAmountsOut( + uint256 amountIn, + address reserveIn, + address reserveOut, + bool withFlash + ) + external + view + returns ( + uint256, + uint256, + uint256, + uint256, + address[] memory + ); + + /** + * @dev Returns the minimum input asset amount required to buy the given output asset amount and the prices + * @param amountOut Amount of reserveOut + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @return uint256 Amount in of the reserveIn + * @return uint256 The price of in amount denominated in the reserveOut currency (18 decimals) + * @return uint256 In amount of reserveIn value denominated in USD (8 decimals) + * @return uint256 Out amount of reserveOut value denominated in USD (8 decimals) + * @return address[] The exchange path + */ + function getAmountsIn( + uint256 amountOut, + address reserveIn, + address reserveOut, + bool withFlash + ) + external + view + returns ( + uint256, + uint256, + uint256, + uint256, + address[] memory + ); +} diff --git a/contracts/interfaces/IERC20WithPermit.sol b/contracts/interfaces/IERC20WithPermit.sol new file mode 100644 index 00000000..46466b90 --- /dev/null +++ b/contracts/interfaces/IERC20WithPermit.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; + +import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; + +interface IERC20WithPermit is IERC20 { + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; +} diff --git a/contracts/interfaces/IUniswapV2Router02.sol b/contracts/interfaces/IUniswapV2Router02.sol new file mode 100644 index 00000000..1b1dc475 --- /dev/null +++ b/contracts/interfaces/IUniswapV2Router02.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; + +interface IUniswapV2Router02 { + function swapExactTokensForTokens( + uint256 amountIn, + uint256 amountOutMin, + address[] calldata path, + address to, + uint256 deadline + ) external returns (uint256[] memory amounts); + + function swapTokensForExactTokens( + uint256 amountOut, + uint256 amountInMax, + address[] calldata path, + address to, + uint256 deadline + ) external returns (uint256[] memory amounts); + + function getAmountsOut(uint256 amountIn, address[] calldata path) + external + view + returns (uint256[] memory amounts); + + function getAmountsIn(uint256 amountOut, address[] calldata path) + external + view + returns (uint256[] memory amounts); +} From 688b62fed2252c8a6d6665e132d5b17db3300c01 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 11 Jan 2021 21:15:47 -0500 Subject: [PATCH 016/219] Added gas tracking --- gas-tracker.ts | 8 ++++++++ helpers/contracts-deployments.ts | 5 +++-- helpers/contracts-helpers.ts | 11 ++++++++++- helpers/init-helpers.ts | 16 +++++++++++++++- helpers/oracles-helpers.ts | 12 ++++++++++++ markets/uniswap/commons.ts | 4 ++-- tasks/full/1_address_provider.ts | 8 +++++++- tasks/full/3_oracles.ts | 5 ++++- tasks/full/5_initialize.ts | 3 +++ tasks/migrations/aave.mainnet.ts | 2 ++ tasks/migrations/uniswap.mainnet.ts | 6 +++++- 11 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 gas-tracker.ts diff --git a/gas-tracker.ts b/gas-tracker.ts new file mode 100644 index 00000000..fbd2c48c --- /dev/null +++ b/gas-tracker.ts @@ -0,0 +1,8 @@ +// Should be a ts file that has a global var var gas = 0; +import { BigNumber } from 'ethers'; + +export var totalGas:BigNumber = BigNumber.from(0); + +export function addGas(amount: BigNumber) { + totalGas = totalGas.add(amount); +} \ No newline at end of file diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 739ade34..7152a649 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -11,7 +11,6 @@ import { PoolConfiguration, eEthereumNetwork, } from './types'; - import { MintableERC20 } from '../types/MintableERC20'; import { MockContract } from 'ethereum-waffle'; import { getReservesConfigByPool } from './configuration'; @@ -58,6 +57,7 @@ import { MintableDelegationERC20 } from '../types/MintableDelegationERC20'; import { readArtifact as buidlerReadArtifact } from '@nomiclabs/buidler/plugins'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { LendingPoolLibraryAddresses } from '../types/LendingPoolFactory'; +import { addGas } from '../gas-tracker'; const readArtifact = async (id: string) => { if (DRE.network.name === eEthereumNetwork.buidlerevm) { @@ -71,7 +71,8 @@ export const deployLendingPoolAddressesProvider = async (marketId: string, verif eContractid.LendingPoolAddressesProvider, [marketId], verify - ); + ) + export const deployLendingPoolAddressesProviderRegistry = async (verify?: boolean) => withSaveAndVerify( diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index df306c2a..c4f72403 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -16,7 +16,9 @@ import { MintableERC20 } from '../types/MintableERC20'; import { Artifact } from 'hardhat/types'; import { Artifact as BuidlerArtifact } from '@nomiclabs/buidler/types'; import { verifyContract } from './etherscan-verification'; -import { getIErc20Detailed } from './contracts-getters'; +import { getIErc20Detailed, getFirstSigner } from './contracts-getters'; +import { addGas, totalGas } from '../gas-tracker'; + export type MockTokenMap = { [symbol: string]: MintableERC20 }; @@ -88,6 +90,13 @@ export const withSaveAndVerify = async ( args: (string | string[])[], verify?: boolean ): Promise => { + // const signer = await getFirstSigner(); + // const factory = ethers.ContractFactory.fromSolidity(instance); + // const gasCost = await signer.estimateGas(await factory.getDeployTransaction()); + // console.log("TEST:", gasCost.toString()); + addGas(instance.deployTransaction.gasLimit); + console.log("Current totalGas value:", totalGas); + console.log("LOGGED GAS LIMIT:", instance.deployTransaction.gasLimit); await waitForTx(instance.deployTransaction); await registerContractInJsonDb(id, instance); if (DRE.network.name.includes('tenderly')) { diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index e80d2f91..2083e0df 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -25,6 +25,7 @@ import { } from './contracts-deployments'; import { ZERO_ADDRESS } from './constants'; import { isZeroAddress } from 'ethereumjs-util'; +import { addGas } from '../gas-tracker'; const chooseATokenDeployment = (id: eContractid) => { switch (id) { @@ -53,6 +54,7 @@ export const initReservesByHelper = async ( const poolAddress = await addressProvider.getLendingPool(); // Set aTokenAndRatesDeployer as temporal admin + addGas(await addressProvider.estimateGas.setPoolAdmin(atokenAndRatesDeployer.address)); await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address)); // CHUNK CONFIGURATION @@ -130,6 +132,7 @@ export const initReservesByHelper = async ( reservesDecimals.push(reserveDecimals); } + // tx1 and tx2 gas is accounted for later. // Deploy stable and variable deployers and save implementations const tx1 = await waitForTx( await stableAndVariableDeployer.initDeployment(tokens, symbols, incentivesController) @@ -158,7 +161,7 @@ export const initReservesByHelper = async ( console.log(' * gasUsed: debtTokens batch', tx1.gasUsed.toString()); console.log(' * gasUsed: aTokens and Strategy batch', tx2.gasUsed.toString()); gasUsage = gasUsage.add(tx1.gasUsed).add(tx2.gasUsed); - + addGas(gasUsage); 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) || []; @@ -352,6 +355,7 @@ export const configureReservesByHelper = async ( } if (tokens.length) { // Set aTokenAndRatesDeployer as temporal admin + addGas(await addressProvider.estimateGas.setPoolAdmin(atokenAndRatesDeployer.address)); await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address)); // Deploy init per chunks @@ -366,6 +370,15 @@ export const configureReservesByHelper = async ( console.log(`- Configure reserves in ${chunkedTokens.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedTokens.length; chunkIndex++) { + addGas(await atokenAndRatesDeployer.estimateGas.configureReserves( + chunkedTokens[chunkIndex], + chunkedBase[chunkIndex], + chunkedliquidationThresholds[chunkIndex], + chunkedliquidationBonuses[chunkIndex], + chunkedReserveFactors[chunkIndex], + chunkedStableRatesEnabled[chunkIndex], + { gasLimit: 12000000 } + )); await waitForTx( await atokenAndRatesDeployer.configureReserves( chunkedTokens[chunkIndex], @@ -380,6 +393,7 @@ export const configureReservesByHelper = async ( console.log(` - Init for: ${chunkedSymbols[chunkIndex].join(', ')}`); } // Set deployer back as admin + addGas(await addressProvider.estimateGas.setPoolAdmin(admin)); await waitForTx(await addressProvider.setPoolAdmin(admin)); } }; diff --git a/helpers/oracles-helpers.ts b/helpers/oracles-helpers.ts index 45cec5e2..7f8ecb81 100644 --- a/helpers/oracles-helpers.ts +++ b/helpers/oracles-helpers.ts @@ -13,6 +13,7 @@ import {MockAggregator} from '../types/MockAggregator'; import {deployMockAggregator} from './contracts-deployments'; import {chunk, waitForTx} from './misc-utils'; import {getStableAndVariableTokensHelper} from './contracts-getters'; +import { addGas } from '../gas-tracker'; export const setInitialMarketRatesInRatesOracleByHelper = async ( marketRates: iMultiPoolsAssets, @@ -45,12 +46,20 @@ export const setInitialMarketRatesInRatesOracleByHelper = async ( const chunkedSymbols = chunk(symbols, ratesChunks); // Set helper as owner + addGas(await lendingRateOracleInstance.estimateGas.transferOwnership(stableAndVariableTokenHelper.address)); await waitForTx( await lendingRateOracleInstance.transferOwnership(stableAndVariableTokenHelper.address) ); console.log(`- Oracle borrow initalization in ${chunkedTokens.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedTokens.length; chunkIndex++) { + + addGas(await stableAndVariableTokenHelper.estimateGas.setOracleBorrowRates( + chunkedTokens[chunkIndex], + chunkedRates[chunkIndex], + lendingRateOracleInstance.address + )); + const tx3 = await waitForTx( await stableAndVariableTokenHelper.setOracleBorrowRates( chunkedTokens[chunkIndex], @@ -61,6 +70,7 @@ export const setInitialMarketRatesInRatesOracleByHelper = async ( console.log(` - Setted Oracle Borrow Rates for: ${chunkedSymbols[chunkIndex].join(', ')}`); } // Set back ownership + addGas(await stableAndVariableTokenHelper.estimateGas.setOracleOwnership(lendingRateOracleInstance.address, admin)); await waitForTx( await stableAndVariableTokenHelper.setOracleOwnership(lendingRateOracleInstance.address, admin) ); @@ -78,6 +88,7 @@ export const setInitialAssetPricesInOracle = async ( const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[ assetAddressIndex ]; + addGas(await priceOracleInstance.estimateGas.setAssetPrice(assetAddress, price)); await waitForTx(await priceOracleInstance.setAssetPrice(assetAddress, price)); } }; @@ -94,6 +105,7 @@ export const setAssetPricesInOracle = async ( const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[ assetAddressIndex ]; + addGas(await priceOracleInstance.estimateGas.setAssetPrice(assetAddress, price)); await waitForTx(await priceOracleInstance.setAssetPrice(assetAddress, price)); } }; diff --git a/markets/uniswap/commons.ts b/markets/uniswap/commons.ts index db319e66..619a5e80 100644 --- a/markets/uniswap/commons.ts +++ b/markets/uniswap/commons.ts @@ -126,7 +126,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.kovan]: '',//'0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', - [eEthereumNetwork.main]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', + [eEthereumNetwork.main]: '', //'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', }, TokenDistributor: { @@ -144,7 +144,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.buidlerevm]: '', [EthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', [EthereumNetwork.ropsten]: ZERO_ADDRESS, - [EthereumNetwork.main]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', + [EthereumNetwork.main]: '', //'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', }, FallbackOracle: { diff --git a/tasks/full/1_address_provider.ts b/tasks/full/1_address_provider.ts index 7c0ed167..ad7fefd9 100644 --- a/tasks/full/1_address_provider.ts +++ b/tasks/full/1_address_provider.ts @@ -18,8 +18,10 @@ import { } from '../../helpers/contracts-getters'; import { formatEther, isAddress, parseEther } from 'ethers/lib/utils'; import { isZeroAddress } from 'ethereumjs-util'; -import { Signer } from 'ethers'; +import { Signer, BigNumber } from 'ethers'; import { parse } from 'path'; +import { addGas } from '../../gas-tracker'; +//import BigNumber from 'bignumber.js'; task( 'full:deploy-address-provider', @@ -92,6 +94,10 @@ task( // ); // 4. Set pool admins + + + addGas(await addressesProvider.estimateGas.setPoolAdmin(await getGenesisPoolAdmin(poolConfig))); + addGas(await addressesProvider.estimateGas.setEmergencyAdmin(await getEmergencyAdmin(poolConfig))); await waitForTx(await addressesProvider.setPoolAdmin(await getGenesisPoolAdmin(poolConfig))); await waitForTx(await addressesProvider.setEmergencyAdmin(await getEmergencyAdmin(poolConfig))); diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index b064328f..edcef77d 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -17,6 +17,7 @@ import { getLendingRateOracle, getPairsTokenAggregator, } from '../../helpers/contracts-getters'; +import { addGas } from '../../gas-tracker'; task('full:deploy-oracles', 'Deploy oracles for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') @@ -66,8 +67,10 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') admin ); } - + console.log("ORACLES: %s and %s", aaveOracle.address, lendingRateOracle.address); // Register the proxy price provider on the addressesProvider + addGas(await addressesProvider.estimateGas.setPriceOracle(aaveOracle.address)); + addGas(await addressesProvider.estimateGas.setLendingRateOracle(lendingRateOracle.address)); await waitForTx(await addressesProvider.setPriceOracle(aaveOracle.address)); await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); } catch (error) { diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 444f55d8..a40d0f3c 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -19,6 +19,7 @@ import { getLendingPoolAddressesProvider, } from '../../helpers/contracts-getters'; import { ZERO_ADDRESS } from '../../helpers/constants'; +import { addGas } from '../../gas-tracker'; task('full:initialize-lending-pool', 'Initialize lending pool configuration.') .addFlag('verify', 'Verify contracts at Etherscan') @@ -47,6 +48,8 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') await configureReservesByHelper(ReservesConfig, reserveAssets, testHelpers, admin); const collateralManager = await deployLendingPoolCollateralManager(verify); + + addGas(await addressesProvider.estimateGas.setLendingPoolCollateralManager(collateralManager.address)); await waitForTx( await addressesProvider.setLendingPoolCollateralManager(collateralManager.address) ); diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index c8ae5430..deba3b04 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -4,6 +4,7 @@ import {checkVerification} from '../../helpers/etherscan-verification'; import {ConfigNames} from '../../helpers/configuration'; import {EthereumNetworkNames} from '../../helpers/types'; import {printContracts} from '../../helpers/misc-utils'; +import {totalGas} from '../../gas-tracker'; task('aave:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') @@ -56,4 +57,5 @@ task('aave:mainnet', 'Deploy development enviroment') } console.log('\nFinished migrations'); printContracts(); + console.log("Total gas used:", totalGas); }); diff --git a/tasks/migrations/uniswap.mainnet.ts b/tasks/migrations/uniswap.mainnet.ts index 7945dca6..5657f6eb 100644 --- a/tasks/migrations/uniswap.mainnet.ts +++ b/tasks/migrations/uniswap.mainnet.ts @@ -4,6 +4,7 @@ import {checkVerification} from '../../helpers/etherscan-verification'; import {ConfigNames} from '../../helpers/configuration'; import {EthereumNetworkNames} from '../../helpers/types'; import {printContracts} from '../../helpers/misc-utils'; +import {totalGas} from '../../gas-tracker'; task('uniswap:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') @@ -23,12 +24,14 @@ task('uniswap:mainnet', 'Deploy development enviroment') const provider = new DRE.ethers.providers.Web3Provider(DRE.tenderlyRPC as any); DRE.ethers.provider = provider; } + // addGas(1); + // console.log(totalGas); console.log('Migration started\n'); console.log('1. Deploy address provider'); await DRE.run('full:deploy-address-provider', {pool: POOL_NAME}); - + console.log('2. Deploy lending pool'); await DRE.run('full:deploy-lending-pool'); @@ -56,4 +59,5 @@ task('uniswap:mainnet', 'Deploy development enviroment') } console.log('\nFinished migrations'); printContracts(); + console.log("Total gas used:", totalGas); }); From 917f6329804f9974a669fa2eaa5b9c8df5bfa3b6 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 13 Jan 2021 01:05:44 -0500 Subject: [PATCH 017/219] Added unique prefix functionality --- helpers/contracts-getters.ts | 24 ++-- helpers/types.ts | 23 +-- markets/aave/commons.ts | 9 +- markets/uniswap/commons.ts | 31 +++-- markets/uniswap/index.ts | 42 +++--- package-lock.json | 261 +++++++++++++++++++++++------------ 6 files changed, 248 insertions(+), 142 deletions(-) diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index 65834cc6..c1f7c4a4 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -168,19 +168,19 @@ export const getPairsTokenAggregator = ( }, aggregatorsAddresses: { [tokenSymbol: string]: tEthereumAddress } ): [string[], string[]] => { - const { ETH, USD, WETH, ...assetsAddressesWithoutEth } = allAssetsAddresses; - + const { ETH, USD, WETH, UniWETH, ...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]; - } + //if (true/*tokenSymbol !== 'WETH' && tokenSymbol !== 'ETH' && tokenSymbol !== 'UniWETH'*/) { + 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); diff --git a/helpers/types.ts b/helpers/types.ts index bbb16389..3f810694 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -201,8 +201,13 @@ export interface iAssetBase { USD: T; REN: T; ENJ: T; - WETHDAI: T; - WETHWBTC: T; + UniWETH: T; + UniWBTC: T; + UniDAI: T; + UniUSDC: T; + UniUSDT: T; + UniWETHDAI: T; + UniWETHWBTC: T; } export type iAssetsWithoutETH = Omit, 'ETH'>; @@ -235,13 +240,13 @@ export type iAavePoolAssets = Pick< export type iUniswapPoolAssets = Pick< iAssetsWithoutUSD, - | 'DAI' - | 'USDC' - | 'USDT' - | 'WBTC' - | 'WETH' - | 'WETHDAI' - | 'WETHWBTC' + | 'UniDAI' + | 'UniUSDC' + | 'UniUSDT' + | 'UniWBTC' + | 'UniWETH' + | 'UniWETHDAI' + | 'UniWETHWBTC' >; export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index fecd714f..1d4b1e4a 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -23,8 +23,13 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), - WETHDAI: oneEther.multipliedBy('22.407436').toFixed(), - WETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), + UniDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + UniUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + UniUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + UniWBTC: oneEther.multipliedBy('47.332685').toFixed(), + UniWETH: oneEther.toFixed(), + UniWETHDAI: oneEther.multipliedBy('22.407436').toFixed(), + UniWETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; // ---------------- diff --git a/markets/uniswap/commons.ts b/markets/uniswap/commons.ts index 619a5e80..65378c32 100644 --- a/markets/uniswap/commons.ts +++ b/markets/uniswap/commons.ts @@ -23,8 +23,13 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), - WETHDAI: oneEther.multipliedBy('22.407436').toFixed(), - WETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), + UniDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + UniUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + UniUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + UniWBTC: oneEther.multipliedBy('47.332685').toFixed(), + UniWETH: oneEther.toFixed(), + UniWETHDAI: oneEther.multipliedBy('22.407436').toFixed(), + UniWETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; // ---------------- @@ -54,25 +59,25 @@ export const CommonsConfig: ICommonConfiguration = { }, // TODO: reorg alphabetically, checking the reason of tests failing LendingRateOracleRatesCommon: { - WETH: { + UniWETH: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - DAI: { + UniDAI: { borrowRate: oneRay.multipliedBy(0.039).toFixed(), }, - USDC: { + UniUSDC: { borrowRate: oneRay.multipliedBy(0.039).toFixed(), }, - USDT: { + UniUSDT: { borrowRate: oneRay.multipliedBy(0.035).toFixed(), }, - WBTC: { + UniWBTC: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - WETHDAI: { + UniWETHDAI: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - WETHWBTC: { + UniWETHWBTC: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, }, @@ -226,9 +231,13 @@ export const CommonsConfig: ICommonConfiguration = { WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4', ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', + UniUSDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', + UniWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', + UniUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', + UniDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', + UniWETHDAI: ZERO_ADDRESS, + UniWETHWBTC: ZERO_ADDRESS, USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', - WETHDAI: ZERO_ADDRESS, - WETHWBTC: ZERO_ADDRESS, }, [EthereumNetwork.tenderlyMain]: { AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', diff --git a/markets/uniswap/index.ts b/markets/uniswap/index.ts index e210c630..0447ca15 100644 --- a/markets/uniswap/index.ts +++ b/markets/uniswap/index.ts @@ -21,26 +21,26 @@ export const UniswapConfig: IUniswapConfiguration = { MarketId: 'Uniswap V2 market', ProviderId: 2, ReservesConfig: { - DAI: strategyDAI, - USDC: strategyUSDC, - USDT: strategyUSDT, - WBTC: strategyWBTC, - WETH: strategyWETH, - WETHDAI: strategyWETHDAI, - WETHWBTC: strategyWETHWBTC + UniWETH: strategyWETH, + UniDAI: strategyDAI, + UniUSDC: strategyUSDC, + UniUSDT: strategyUSDT, + UniWBTC: strategyWBTC, + UniWETHDAI: strategyWETHDAI, + UniWETHWBTC: strategyWETHWBTC }, ReserveAssets: { [eEthereumNetwork.buidlerevm]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.coverage]: {}, [EthereumNetwork.kovan]: { - DAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', - USDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', - USDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', - WBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', - WETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', - WETHDAI: '0x7d3A67ab574abD3F9849e5fcDa48c19939d032b4', - WETHWBTC: '0x342e78bf229Cd2a750E80D7D7c2C185455979b91', + UniDAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', + UniUSDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', + UniUSDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', + UniWBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', + UniWETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', + UniWETHDAI: '0x7d3A67ab574abD3F9849e5fcDa48c19939d032b4', + uniWETHWBTC: '0x342e78bf229Cd2a750E80D7D7c2C185455979b91', }, [EthereumNetwork.ropsten]: { // AAVE: '', @@ -65,13 +65,13 @@ export const UniswapConfig: IUniswapConfiguration = { // ZRX: '0x02d7055704EfF050323A2E5ee4ba05DB2A588959', }, [EthereumNetwork.main]: { - DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', - WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', - WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - WETHDAI: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', - WETHWBTC: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', + UniDAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + UniUSDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + UniUSDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + UniWBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + UniWETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + UniWETHDAI: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', + UniWETHWBTC: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', }, [EthereumNetwork.tenderlyMain]: { DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', diff --git a/package-lock.json b/package-lock.json index dfdeb1a5..39dac6d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5583,12 +5583,14 @@ "dependencies": { "ansi-regex": { "version": "4.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "ansi-styles": { "version": "3.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -5596,7 +5598,8 @@ }, "bindings": { "version": "1.5.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, "requires": { "file-uri-to-path": "1.0.0" @@ -5604,7 +5607,8 @@ }, "bip66": { "version": "1.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", "dev": true, "requires": { "safe-buffer": "^5.0.1" @@ -5612,17 +5616,20 @@ }, "bn.js": { "version": "4.11.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, "brorand": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, "browserify-aes": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { "buffer-xor": "^1.0.3", @@ -5635,22 +5642,26 @@ }, "buffer-from": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, "buffer-xor": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, "camelcase": { "version": "5.3.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "cipher-base": { "version": "1.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -5659,7 +5670,8 @@ }, "cliui": { "version": "5.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { "string-width": "^3.1.0", @@ -5669,7 +5681,8 @@ }, "color-convert": { "version": "1.9.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" @@ -5677,12 +5690,14 @@ }, "color-name": { "version": "1.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "create-hash": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { "cipher-base": "^1.0.1", @@ -5694,7 +5709,8 @@ }, "create-hmac": { "version": "1.1.7", - "bundled": true, + "resolved": false, + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { "cipher-base": "^1.0.3", @@ -5707,7 +5723,8 @@ }, "cross-spawn": { "version": "6.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { "nice-try": "^1.0.4", @@ -5719,12 +5736,14 @@ }, "decamelize": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "drbg.js": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", "dev": true, "requires": { "browserify-aes": "^1.0.6", @@ -5734,7 +5753,8 @@ }, "elliptic": { "version": "6.5.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -5748,12 +5768,14 @@ }, "emoji-regex": { "version": "7.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "end-of-stream": { "version": "1.4.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { "once": "^1.4.0" @@ -5761,7 +5783,8 @@ }, "ethereumjs-util": { "version": "6.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", "dev": true, "requires": { "bn.js": "^4.11.0", @@ -5775,7 +5798,8 @@ }, "ethjs-util": { "version": "0.1.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", "dev": true, "requires": { "is-hex-prefixed": "1.0.0", @@ -5784,7 +5808,8 @@ }, "evp_bytestokey": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, "requires": { "md5.js": "^1.3.4", @@ -5793,7 +5818,8 @@ }, "execa": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { "cross-spawn": "^6.0.0", @@ -5807,12 +5833,14 @@ }, "file-uri-to-path": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "dev": true }, "find-up": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { "locate-path": "^3.0.0" @@ -5820,12 +5848,14 @@ }, "get-caller-file": { "version": "2.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-stream": { "version": "4.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "requires": { "pump": "^3.0.0" @@ -5833,7 +5863,8 @@ }, "hash-base": { "version": "3.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, "requires": { "inherits": "^2.0.1", @@ -5842,7 +5873,8 @@ }, "hash.js": { "version": "1.1.7", - "bundled": true, + "resolved": false, + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -5851,7 +5883,8 @@ }, "hmac-drbg": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { "hash.js": "^1.0.3", @@ -5861,37 +5894,44 @@ }, "inherits": { "version": "2.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "invert-kv": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "is-hex-prefixed": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", "dev": true }, "is-stream": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, "isexe": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "keccak": { "version": "1.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", "dev": true, "requires": { "bindings": "^1.2.1", @@ -5902,7 +5942,8 @@ }, "lcid": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { "invert-kv": "^2.0.0" @@ -5910,7 +5951,8 @@ }, "locate-path": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { "p-locate": "^3.0.0", @@ -5919,7 +5961,8 @@ }, "map-age-cleaner": { "version": "0.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", "dev": true, "requires": { "p-defer": "^1.0.0" @@ -5927,7 +5970,8 @@ }, "md5.js": { "version": "1.3.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, "requires": { "hash-base": "^3.0.0", @@ -5937,7 +5981,8 @@ }, "mem": { "version": "4.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, "requires": { "map-age-cleaner": "^0.1.1", @@ -5947,32 +5992,38 @@ }, "mimic-fn": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "minimalistic-assert": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, "minimalistic-crypto-utils": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", "dev": true }, "nan": { "version": "2.14.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "dev": true }, "nice-try": { "version": "1.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "npm-run-path": { "version": "2.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { "path-key": "^2.0.0" @@ -5980,7 +6031,8 @@ }, "once": { "version": "1.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { "wrappy": "1" @@ -5988,7 +6040,8 @@ }, "os-locale": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { "execa": "^1.0.0", @@ -5998,22 +6051,26 @@ }, "p-defer": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", "dev": true }, "p-finally": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, "p-is-promise": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", "dev": true }, "p-limit": { "version": "2.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -6021,7 +6078,8 @@ }, "p-locate": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { "p-limit": "^2.0.0" @@ -6029,22 +6087,26 @@ }, "p-try": { "version": "2.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "path-exists": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, "path-key": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "pump": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -6053,17 +6115,20 @@ }, "require-directory": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "ripemd160": { "version": "2.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { "hash-base": "^3.0.0", @@ -6072,7 +6137,8 @@ }, "rlp": { "version": "2.2.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==", "dev": true, "requires": { "bn.js": "^4.11.1", @@ -6081,12 +6147,14 @@ }, "safe-buffer": { "version": "5.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", "dev": true }, "secp256k1": { "version": "3.7.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", "dev": true, "requires": { "bindings": "^1.5.0", @@ -6101,17 +6169,20 @@ }, "semver": { "version": "5.7.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true }, "set-blocking": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "sha.js": { "version": "2.4.11", - "bundled": true, + "resolved": false, + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -6120,7 +6191,8 @@ }, "shebang-command": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { "shebang-regex": "^1.0.0" @@ -6128,22 +6200,26 @@ }, "shebang-regex": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, "signal-exit": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, "source-map": { "version": "0.6.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "source-map-support": { "version": "0.5.12", - "bundled": true, + "resolved": false, + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -6152,7 +6228,8 @@ }, "string-width": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { "emoji-regex": "^7.0.1", @@ -6162,7 +6239,8 @@ }, "strip-ansi": { "version": "5.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { "ansi-regex": "^4.1.0" @@ -6170,12 +6248,14 @@ }, "strip-eof": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "strip-hex-prefix": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", "dev": true, "requires": { "is-hex-prefixed": "1.0.0" @@ -6183,7 +6263,8 @@ }, "which": { "version": "1.3.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -6191,12 +6272,14 @@ }, "which-module": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "wrap-ansi": { "version": "5.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { "ansi-styles": "^3.2.0", @@ -6206,17 +6289,20 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "y18n": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yargs": { "version": "13.2.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", "dev": true, "requires": { "cliui": "^5.0.0", @@ -6234,7 +6320,8 @@ }, "yargs-parser": { "version": "13.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { "camelcase": "^5.0.0", From 4f5828457bd032a3a4d8033074545a56af2bbd7d Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 14 Jan 2021 18:39:18 -0500 Subject: [PATCH 018/219] Removed redundancies --- markets/uniswap/commons.ts | 97 ++++++-------------------------------- 1 file changed, 15 insertions(+), 82 deletions(-) diff --git a/markets/uniswap/commons.ts b/markets/uniswap/commons.ts index 65378c32..db06cfa0 100644 --- a/markets/uniswap/commons.ts +++ b/markets/uniswap/commons.ts @@ -166,100 +166,33 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.buidlerevm]: {}, [EthereumNetwork.kovan]: { - AAVE: '0xd04647B7CB523bb9f26730E9B6dE1174db7591Ad', - BAT: '0x0e4fcEC26c9f85c3D714370c98f43C4E02Fc35Ae', - BUSD: '0xbF7A18ea5DE0501f7559144e702b29c55b055CcB', - DAI: '0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', - ENJ: '0xfaDbe2ee798889F02d1d39eDaD98Eff4c7fe95D4', - KNC: '0xb8E8130d244CFd13a75D6B9Aee029B1C33c808A7', - LINK: '0x3Af8C569ab77af5230596Acf0E8c2F9351d24C38', - MANA: '0x1b93D8E109cfeDcBb3Cc74eD761DE286d5771511', - MKR: '0x0B156192e04bAD92B6C1C13cf8739d14D78D5701', - REN: '0xF1939BECE7708382b5fb5e559f630CB8B39a10ee', - SNX: '0xF9A76ae7a1075Fe7d646b06fF05Bd48b9FA5582e', - SUSD: '0xb343e7a1aF578FA35632435243D814e7497622f7', - TUSD: '0x7aeCF1c19661d12E962b69eBC8f6b2E63a55C660', - UNI: '0x17756515f112429471F86f98D5052aCB6C47f6ee', - USDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', - USDT: '0x0bF499444525a23E7Bb61997539725cA2e928138', - WBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', - YFI: '0xC5d1B1DEb2992738C0273408ac43e1e906086B6C', - ZRX: '0xBc3f28Ccc21E9b5856E81E6372aFf57307E2E883', - USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', - WETHDAI: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - WETHWBTC: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniUSDT: ZERO_ADDRESS, + UniWBTC: ZERO_ADDRESS, + UniUSDC: ZERO_ADDRESS, + UniDAI:ZERO_ADDRESS, + UniWETHDAI: ZERO_ADDRESS, + UniWETHWBTC: ZERO_ADDRESS, + USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', }, [EthereumNetwork.ropsten]: { - AAVE: ZERO_ADDRESS, - BAT: '0xafd8186c962daf599f171b8600f3e19af7b52c92', - BUSD: '0x0A32D96Ff131cd5c3E0E5AAB645BF009Eda61564', - DAI: '0x64b8e49baded7bfb2fd5a9235b2440c0ee02971b', - ENJ: ZERO_ADDRESS, - KNC: '0x19d97ceb36624a31d827032d8216dd2eb15e9845', - LINK: '0xb8c99b98913bE2ca4899CdcaF33a3e519C20EeEc', - MANA: '0xDab909dedB72573c626481fC98CEE1152b81DEC2', - MKR: '0x811B1f727F8F4aE899774B568d2e72916D91F392', - REN: ZERO_ADDRESS, - SNX: '0xA95674a8Ed9aa9D2E445eb0024a9aa05ab44f6bf', - SUSD: '0xe054b4aee7ac7645642dd52f1c892ff0128c98f0', - TUSD: '0x523ac85618df56e940534443125ef16daf785620', - UNI: ZERO_ADDRESS, - USDC: '0xe1480303dde539e2c241bdc527649f37c9cbef7d', - USDT: '0xc08fe0c4d97ccda6b40649c6da621761b628c288', - WBTC: '0x5b8B87A0abA4be247e660B0e0143bB30Cdf566AF', - YFI: ZERO_ADDRESS, - ZRX: '0x1d0052e4ae5b4ae4563cbac50edc3627ca0460d7', - USD: '0x8468b2bDCE073A157E560AA4D9CcF6dB1DB98507', }, [EthereumNetwork.main]: { - AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', - BAT: '0x0d16d4528239e9ee52fa531af613AcdB23D88c94', - BUSD: '0x614715d2Af89E6EC99A233818275142cE88d1Cfd', - DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', - ENJ: '0x24D9aB51950F3d62E9144fdC2f3135DAA6Ce8D1B', - KNC: '0x656c0544eF4C98A6a98491833A89204Abb045d6b', - LINK: '0xDC530D9457755926550b59e8ECcdaE7624181557', - MANA: '0x82A44D92D6c329826dc557c5E1Be6ebeC5D5FeB9', - MKR: '0x24551a8Fb2A7211A25a17B1481f043A8a8adC7f2', - REN: '0x3147D7203354Dc06D9fd350c7a2437bcA92387a4', - SNX: '0x79291A9d692Df95334B1a0B3B4AE6bC606782f8c', - SUSD: '0x8e0b7e6062272B5eF4524250bFFF8e5Bd3497757', - TUSD: '0x3886BA987236181D98F2401c507Fb8BeA7871dF2', - UNI: '0xD6aA3D25116d8dA79Ea0246c4826EB951872e02e', - USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', - USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', - WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', - YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4', - ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', UniUSDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', UniWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', UniUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', UniDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', UniWETHDAI: ZERO_ADDRESS, UniWETHWBTC: ZERO_ADDRESS, - USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [EthereumNetwork.tenderlyMain]: { - AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', - BAT: '0x0d16d4528239e9ee52fa531af613AcdB23D88c94', - BUSD: '0x614715d2Af89E6EC99A233818275142cE88d1Cfd', - DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', - ENJ: '0x24D9aB51950F3d62E9144fdC2f3135DAA6Ce8D1B', - KNC: '0x656c0544eF4C98A6a98491833A89204Abb045d6b', - LINK: '0xDC530D9457755926550b59e8ECcdaE7624181557', - MANA: '0x82A44D92D6c329826dc557c5E1Be6ebeC5D5FeB9', - MKR: '0x24551a8Fb2A7211A25a17B1481f043A8a8adC7f2', - REN: '0x3147D7203354Dc06D9fd350c7a2437bcA92387a4', - SNX: '0x79291A9d692Df95334B1a0B3B4AE6bC606782f8c', - SUSD: '0x8e0b7e6062272B5eF4524250bFFF8e5Bd3497757', - TUSD: '0x3886BA987236181D98F2401c507Fb8BeA7871dF2', - UNI: '0xD6aA3D25116d8dA79Ea0246c4826EB951872e02e', - USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', - USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', - WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', - YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4', - ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', - USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + UniUSDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', + UniWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', + UniUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', + UniDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', + UniWETHDAI: ZERO_ADDRESS, + UniWETHWBTC: ZERO_ADDRESS, + USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, }, ReserveAssets: { From eb38932cc2c7411aa9bb62feae456d3ccabfced7 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 14 Jan 2021 18:43:49 -0500 Subject: [PATCH 019/219] Cleaned comment --- gas-tracker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gas-tracker.ts b/gas-tracker.ts index fbd2c48c..0e165a00 100644 --- a/gas-tracker.ts +++ b/gas-tracker.ts @@ -1,4 +1,6 @@ -// Should be a ts file that has a global var var gas = 0; +/** + * @dev This is a simple script that keeps track of gas spent during deployment. + */ import { BigNumber } from 'ethers'; export var totalGas:BigNumber = BigNumber.from(0); From ccb6e36760ff56d2ff27979e5f126aceb06ae268 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 14 Jan 2021 18:56:18 -0500 Subject: [PATCH 020/219] Slight cleanup --- helpers/contracts-deployments.ts | 1 - helpers/contracts-helpers.ts | 3 +-- helpers/types.ts | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 7152a649..4c4ac58d 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -72,7 +72,6 @@ export const deployLendingPoolAddressesProvider = async (marketId: string, verif [marketId], verify ) - export const deployLendingPoolAddressesProviderRegistry = async (verify?: boolean) => withSaveAndVerify( diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index c4f72403..702e54ad 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -19,7 +19,6 @@ import { verifyContract } from './etherscan-verification'; import { getIErc20Detailed, getFirstSigner } from './contracts-getters'; import { addGas, totalGas } from '../gas-tracker'; - export type MockTokenMap = { [symbol: string]: MintableERC20 }; export const registerContractInJsonDb = async (contractId: string, contractInstance: Contract) => { @@ -96,7 +95,7 @@ export const withSaveAndVerify = async ( // console.log("TEST:", gasCost.toString()); addGas(instance.deployTransaction.gasLimit); console.log("Current totalGas value:", totalGas); - console.log("LOGGED GAS LIMIT:", instance.deployTransaction.gasLimit); + console.log("Logged gas limit:", instance.deployTransaction.gasLimit); await waitForTx(instance.deployTransaction); await registerContractInJsonDb(id, instance); if (DRE.network.name.includes('tenderly')) { diff --git a/helpers/types.ts b/helpers/types.ts index 3f810694..55113100 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -277,8 +277,6 @@ export enum TokenContractId { YFI = 'YFI', UNI = 'UNI', ENJ = 'ENJ', - WETHDAI = 'WETHDAI', - WETHWBTC = 'WETHWBTC', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { From b2123e914ce9e93d89b9602381627449ab5aecc3 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 14 Jan 2021 19:06:29 -0500 Subject: [PATCH 021/219] Slight fix --- helpers/contracts-deployments.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 4c4ac58d..8f7f0c9d 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -57,7 +57,6 @@ import { MintableDelegationERC20 } from '../types/MintableDelegationERC20'; import { readArtifact as buidlerReadArtifact } from '@nomiclabs/buidler/plugins'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { LendingPoolLibraryAddresses } from '../types/LendingPoolFactory'; -import { addGas } from '../gas-tracker'; const readArtifact = async (id: string) => { if (DRE.network.name === eEthereumNetwork.buidlerevm) { @@ -65,13 +64,14 @@ const readArtifact = async (id: string) => { } return (DRE as HardhatRuntimeEnvironment).artifacts.readArtifact(id); }; + export const deployLendingPoolAddressesProvider = async (marketId: string, verify?: boolean) => withSaveAndVerify( await new LendingPoolAddressesProviderFactory(await getFirstSigner()).deploy(marketId), eContractid.LendingPoolAddressesProvider, [marketId], verify - ) + ); export const deployLendingPoolAddressesProviderRegistry = async (verify?: boolean) => withSaveAndVerify( From ed17b5a0379adfc2576ead46c15a691967f61c90 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 14 Jan 2021 20:59:14 -0500 Subject: [PATCH 022/219] Slight cleanup --- helpers/contracts-getters.ts | 2 +- helpers/contracts-helpers.ts | 4 ---- tasks/migrations/aave.mainnet.ts | 2 +- tasks/migrations/uniswap.mainnet.ts | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index c1f7c4a4..f1b847da 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -169,7 +169,7 @@ export const getPairsTokenAggregator = ( aggregatorsAddresses: { [tokenSymbol: string]: tEthereumAddress } ): [string[], string[]] => { const { ETH, USD, WETH, UniWETH, ...assetsAddressesWithoutEth } = allAssetsAddresses; - + const pairs = Object.entries(assetsAddressesWithoutEth).map(([tokenSymbol, tokenAddress]) => { //if (true/*tokenSymbol !== 'WETH' && tokenSymbol !== 'ETH' && tokenSymbol !== 'UniWETH'*/) { const aggregatorAddressIndex = Object.keys(aggregatorsAddresses).findIndex( diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 702e54ad..4b6a2830 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -89,10 +89,6 @@ export const withSaveAndVerify = async ( args: (string | string[])[], verify?: boolean ): Promise => { - // const signer = await getFirstSigner(); - // const factory = ethers.ContractFactory.fromSolidity(instance); - // const gasCost = await signer.estimateGas(await factory.getDeployTransaction()); - // console.log("TEST:", gasCost.toString()); addGas(instance.deployTransaction.gasLimit); console.log("Current totalGas value:", totalGas); console.log("Logged gas limit:", instance.deployTransaction.gasLimit); diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index deba3b04..7ee32855 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -57,5 +57,5 @@ task('aave:mainnet', 'Deploy development enviroment') } console.log('\nFinished migrations'); printContracts(); - console.log("Total gas used:", totalGas); + console.log("Total gas used:", totalGas.toString()); }); diff --git a/tasks/migrations/uniswap.mainnet.ts b/tasks/migrations/uniswap.mainnet.ts index 5657f6eb..ab795d23 100644 --- a/tasks/migrations/uniswap.mainnet.ts +++ b/tasks/migrations/uniswap.mainnet.ts @@ -59,5 +59,5 @@ task('uniswap:mainnet', 'Deploy development enviroment') } console.log('\nFinished migrations'); printContracts(); - console.log("Total gas used:", totalGas); + console.log("Total gas used:", totalGas.toString()); }); From 94dd996666e7184d66a2a7201f8c35f60f16d679 Mon Sep 17 00:00:00 2001 From: David Racero Date: Mon, 18 Jan 2021 15:40:02 +0100 Subject: [PATCH 023/219] Add test cases for FlashLiquidationAdapter --- .../adapters/FlashLiquidationAdapter.sol | 4 +- test/__setup.spec.ts | 1 + test/helpers/make-suite.ts | 1 - test/uniswapAdapters.flashLiquidation.spec.ts | 625 +++++++++++++++--- 4 files changed, 522 insertions(+), 109 deletions(-) diff --git a/contracts/adapters/FlashLiquidationAdapter.sol b/contracts/adapters/FlashLiquidationAdapter.sol index 5ac66e4f..8c4703ce 100644 --- a/contracts/adapters/FlashLiquidationAdapter.sol +++ b/contracts/adapters/FlashLiquidationAdapter.sol @@ -145,11 +145,11 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { vars.userCollateralBalance ); - require(coverAmount >= vars.debtAmountNeeded, 'Not enought cover amount requested'); + require(coverAmount >= vars.debtAmountNeeded, 'FLASH_COVER_NOT_ENOUGH'); uint256 flashLoanDebt = coverAmount.add(premium); - require(IERC20(debtAsset).approve(address(LENDING_POOL), debtToCover), 'Approval error'); + IERC20(debtAsset).approve(address(LENDING_POOL), debtToCover); // Liquidate the user position and release the underlying collateral LENDING_POOL.liquidationCall(collateralAsset, debtAsset, user, debtToCover, false); diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index 53166680..37ff9cfc 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -233,6 +233,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { await waitForTx( await addressesProvider.setLendingPoolCollateralManager(collateralManager.address) ); + await deployMockFlashLoanReceiver(addressesProvider.address); const mockUniswapRouter = await deployMockUniswapRouter(); diff --git a/test/helpers/make-suite.ts b/test/helpers/make-suite.ts index c1bb5b85..4a75e54d 100644 --- a/test/helpers/make-suite.ts +++ b/test/helpers/make-suite.ts @@ -39,7 +39,6 @@ import { solidity } from 'ethereum-waffle'; import { AaveConfig } from '../../markets/aave'; import { FlashLiquidationAdapter } from '../../types'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; -import { hrtime } from 'process'; import { usingTenderly } from '../../helpers/tenderly-utils'; chai.use(bignumberChai()); diff --git a/test/uniswapAdapters.flashLiquidation.spec.ts b/test/uniswapAdapters.flashLiquidation.spec.ts index 2865810d..ff2284e3 100644 --- a/test/uniswapAdapters.flashLiquidation.spec.ts +++ b/test/uniswapAdapters.flashLiquidation.spec.ts @@ -1,34 +1,113 @@ import { makeSuite, TestEnv } from './helpers/make-suite'; import { convertToCurrencyDecimals, - getContract, buildFlashLiquidationAdapterParams, } from '../helpers/contracts-helpers'; import { getMockUniswapRouter } from '../helpers/contracts-getters'; import { deployFlashLiquidationAdapter } from '../helpers/contracts-deployments'; import { MockUniswapV2Router02 } from '../types/MockUniswapV2Router02'; -import { Zero } from '@ethersproject/constants'; import BigNumber from 'bignumber.js'; import { DRE, evmRevert, evmSnapshot, increaseTime } from '../helpers/misc-utils'; import { ethers } from 'ethers'; -import { eContractid, ProtocolErrors, RateMode } from '../helpers/types'; -import { StableDebtToken } from '../types/StableDebtToken'; +import { ProtocolErrors, RateMode } from '../helpers/types'; import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, oneEther } from '../helpers/constants'; import { getUserData } from './helpers/utils/helpers'; import { calcExpectedStableDebtTokenBalance } from './helpers/utils/calculations'; -import { HardhatRuntimeEnvironment } from 'hardhat/types'; -const { parseEther } = ethers.utils; - const { expect } = require('chai'); makeSuite('Uniswap adapters', (testEnv: TestEnv) => { let mockUniswapRouter: MockUniswapV2Router02; + let evmSnapshotId: string; before(async () => { mockUniswapRouter = await getMockUniswapRouter(); }); + const depositAndHFBelowOne = async () => { + const { INVALID_HF } = ProtocolErrors; + const { dai, weth, users, pool, oracle } = testEnv; + const depositor = users[0]; + const borrower = users[1]; + + //mints DAI to depositor + await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access depositor wallet + await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 1 deposits 1000 DAI + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); + //user 2 deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); + + //approve protocol to access the borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 2 borrows + + const userGlobalDataBefore = await pool.getUserAccountData(borrower.address); + const daiPrice = await oracle.getAssetPrice(dai.address); + + const amountDAIToBorrow = await convertToCurrencyDecimals( + dai.address, + new BigNumber(userGlobalDataBefore.availableBorrowsETH.toString()) + .div(daiPrice.toString()) + .multipliedBy(0.95) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.equal( + '8250', + INVALID_HF + ); + + await oracle.setAssetPrice( + dai.address, + new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0) + ); + + const userGlobalData = await pool.getUserAccountData(borrower.address); + + expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( + oneEther.toFixed(0), + INVALID_HF + ); + }; + + beforeEach(async () => { + evmSnapshotId = await evmSnapshot(); + }); + + afterEach(async () => { + await evmRevert(evmSnapshotId); + }); + describe('Flash Liquidation Adapter', () => { + before('Before LendingPool liquidation: set config', () => { + BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); + }); + + after('After LendingPool liquidation: reset config', () => { + BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); + }); + describe('constructor', () => { it('should deploy with correct parameters', async () => { const { addressesProvider, weth } = testEnv; @@ -51,96 +130,11 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { }); }); - describe('executeOperation', () => { - const { INVALID_HF } = ProtocolErrors; + describe('executeOperation: succesfully liquidateCall and swap via Flash Loan with profits', () => { + it('Liquidates the borrow with profit', async () => { + await depositAndHFBelowOne(); + await increaseTime(100); - before('Before LendingPool liquidation: set config', () => { - BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); - }); - - after('After LendingPool liquidation: reset config', () => { - BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); - }); - - it('Deposits WETH, borrows DAI', async () => { - const { dai, weth, users, pool, oracle } = testEnv; - const depositor = users[0]; - const borrower = users[1]; - - //mints DAI to depositor - await dai - .connect(depositor.signer) - .mint(await convertToCurrencyDecimals(dai.address, '1000')); - - //approve protocol to access depositor wallet - await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - //user 1 deposits 1000 DAI - const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await pool - .connect(depositor.signer) - .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); - //user 2 deposits 1 ETH - const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); - - //mints WETH to borrower - await weth - .connect(borrower.signer) - .mint(await convertToCurrencyDecimals(weth.address, '1000')); - - //approve protocol to access the borrower wallet - await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - await pool - .connect(borrower.signer) - .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); - - //user 2 borrows - - const userGlobalData = await pool.getUserAccountData(borrower.address); - const daiPrice = await oracle.getAssetPrice(dai.address); - - const amountDAIToBorrow = await convertToCurrencyDecimals( - dai.address, - new BigNumber(userGlobalData.availableBorrowsETH.toString()) - .div(daiPrice.toString()) - .multipliedBy(0.95) - .toFixed(0) - ); - - await pool - .connect(borrower.signer) - .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address); - - const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); - - expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.bignumber.equal( - '8250', - INVALID_HF - ); - }); - - it('Drop the health factor below 1', async () => { - const { dai, weth, users, pool, oracle } = testEnv; - const borrower = users[1]; - - const daiPrice = await oracle.getAssetPrice(dai.address); - - await oracle.setAssetPrice( - dai.address, - new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0) - ); - - const userGlobalData = await pool.getUserAccountData(borrower.address); - - expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( - oneEther.toFixed(0), - INVALID_HF - ); - }); - - it('Liquidates the borrow', async () => { const { dai, weth, @@ -150,8 +144,16 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { helpersContract, flashLiquidationAdapter, } = testEnv; + const liquidator = users[3]; const borrower = users[1]; + const expectedSwap = ethers.utils.parseEther('0.4'); + + const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); + + // Set how much ETH will be sold and swapped for DAI at Uniswap mock + await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); + const collateralPrice = await oracle.getAssetPrice(weth.address); const principalPrice = await oracle.getAssetPrice(dai.address); const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); @@ -162,6 +164,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { dai.address, borrower.address ); + const collateralDecimals = ( await helpersContract.getReserveConfigurationData(weth.address) ).decimals.toString(); @@ -181,17 +184,12 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { .div(100) .decimalPlaces(0, BigNumber.ROUND_DOWN); - await increaseTime(100); - const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) .multipliedBy(1.0009) .toFixed(0); - await mockUniswapRouter.setAmountOut( - expectedCollateralLiquidated.toString(), - weth.address, - dai.address, - flashLoanDebt + const expectedProfit = ethers.BigNumber.from(expectedCollateralLiquidated.toString()).sub( + expectedSwap ); const params = buildFlashLiquidationAdapterParams( @@ -212,13 +210,23 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { params, 0 ); - await expect(tx) + + // Expect Swapped event + await expect(Promise.resolve(tx)) .to.emit(flashLiquidationAdapter, 'Swapped') + .withArgs(weth.address, dai.address, expectedSwap.toString(), flashLoanDebt); + + // Expect LiquidationCall event + await expect(Promise.resolve(tx)) + .to.emit(pool, 'LiquidationCall') .withArgs( weth.address, dai.address, + borrower.address, + amountToLiquidate.toString(), expectedCollateralLiquidated.toString(), - flashLoanDebt + flashLiquidationAdapter.address, + false ); const userReserveDataAfter = await getUserData( @@ -227,6 +235,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { dai.address, borrower.address ); + const liquidatorWethBalanceAfter = await weth.balanceOf(liquidator.address); const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); @@ -265,7 +274,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( new BigNumber(daiReserveDataBefore.availableLiquidity.toString()) - .plus(amountToLiquidate) + .plus(flashLoanDebt) .toFixed(0), 'Invalid principal available liquidity' ); @@ -276,6 +285,410 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { .toFixed(0), 'Invalid collateral available liquidity' ); + + // Profit after flash loan liquidation + expect(liquidatorWethBalanceAfter).to.be.equal( + liquidatorWethBalanceBefore.add(expectedProfit), + 'Invalid expected WETH profit' + ); + }); + }); + + describe('executeOperation: succesfully liquidateCall and swap via Flash Loan without profits', () => { + it('Liquidates the borrow', async () => { + await depositAndHFBelowOne(); + await increaseTime(100); + + const { + dai, + weth, + users, + pool, + oracle, + helpersContract, + flashLiquidationAdapter, + } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); + + const collateralPrice = await oracle.getAssetPrice(weth.address); + const principalPrice = await oracle.getAssetPrice(dai.address); + const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(dai.address) + ).decimals.toString(); + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + + const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div( + new BigNumber(collateralPrice.toString()).times( + new BigNumber(10).pow(principalDecimals) + ) + ) + .div(100) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) + .multipliedBy(1.0009) + .toFixed(0); + + // Set how much ETH will be sold and swapped for DAI at Uniswap mock + await ( + await mockUniswapRouter.setAmountToSwap( + weth.address, + expectedCollateralLiquidated.toString() + ) + ).wait(); + + const params = buildFlashLiquidationAdapterParams( + weth.address, + dai.address, + borrower.address, + amountToLiquidate, + false + ); + const tx = await pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [dai.address], + [amountToLiquidate], + [0], + borrower.address, + params, + 0 + ); + + // Expect Swapped event + await expect(Promise.resolve(tx)) + .to.emit(flashLiquidationAdapter, 'Swapped') + .withArgs( + weth.address, + dai.address, + expectedCollateralLiquidated.toString(), + flashLoanDebt + ); + + // Expect LiquidationCall event + await expect(Promise.resolve(tx)) + .to.emit(pool, 'LiquidationCall') + .withArgs( + weth.address, + dai.address, + borrower.address, + amountToLiquidate.toString(), + expectedCollateralLiquidated.toString(), + flashLiquidationAdapter.address, + false + ); + + const userReserveDataAfter = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + const liquidatorWethBalanceAfter = await weth.balanceOf(liquidator.address); + + const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); + const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + + if (!tx.blockNumber) { + expect(false, 'Invalid block number'); + return; + } + const txTimestamp = new BigNumber( + (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp + ); + + const stableDebtBeforeTx = calcExpectedStableDebtTokenBalance( + userReserveDataBefore.principalStableDebt, + userReserveDataBefore.stableBorrowRate, + userReserveDataBefore.stableRateLastUpdated, + txTimestamp + ); + + expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( + stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), + 'Invalid user debt after liquidation' + ); + + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( + daiReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + daiReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + + expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(daiReserveDataBefore.availableLiquidity.toString()) + .plus(flashLoanDebt) + .toFixed(0), + 'Invalid principal available liquidity' + ); + + expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) + .minus(expectedCollateralLiquidated) + .toFixed(0), + 'Invalid collateral available liquidity' + ); + + // Net Profit == 0 after flash loan liquidation + expect(liquidatorWethBalanceAfter).to.be.equal( + liquidatorWethBalanceBefore, + 'Invalid expected WETH profit' + ); + }); + }); + + describe('executeOperation: succesfully liquidateCall all available debt and swap via Flash Loan ', () => { + it('Liquidates the borrow', async () => { + await depositAndHFBelowOne(); + await increaseTime(100); + + const { + dai, + weth, + users, + pool, + oracle, + helpersContract, + flashLiquidationAdapter, + } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); + + const collateralPrice = await oracle.getAssetPrice(weth.address); + const principalPrice = await oracle.getAssetPrice(dai.address); + const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(dai.address) + ).decimals.toString(); + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + const extraAmount = new BigNumber(amountToLiquidate).times('1.15').toFixed(0); + + const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div( + new BigNumber(collateralPrice.toString()).times( + new BigNumber(10).pow(principalDecimals) + ) + ) + .div(100) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + const flashLoanDebt = new BigNumber(extraAmount.toString()).multipliedBy(1.0009).toFixed(0); + + // Set how much ETH will be sold and swapped for DAI at Uniswap mock + await ( + await mockUniswapRouter.setAmountToSwap( + weth.address, + expectedCollateralLiquidated.toString() + ) + ).wait(); + + const params = buildFlashLiquidationAdapterParams( + weth.address, + dai.address, + borrower.address, + MAX_UINT_AMOUNT, + false + ); + const tx = await pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [dai.address], + [extraAmount], + [0], + borrower.address, + params, + 0 + ); + + // Expect Swapped event + await expect(Promise.resolve(tx)) + .to.emit(flashLiquidationAdapter, 'Swapped') + .withArgs( + weth.address, + dai.address, + expectedCollateralLiquidated.toString(), + flashLoanDebt + ); + + // Expect LiquidationCall event + await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); + }); + }); + + describe('executeOperation: invalid params', async () => { + it('Revert if debt asset is different than requested flash loan token', async () => { + await depositAndHFBelowOne(); + + const { dai, weth, users, pool, helpersContract, flashLiquidationAdapter } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + const expectedSwap = ethers.utils.parseEther('0.4'); + + // Set how much ETH will be sold and swapped for DAI at Uniswap mock + await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); + + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + + // Wrong debt asset + const params = buildFlashLiquidationAdapterParams( + weth.address, + weth.address, // intentionally bad + borrower.address, + amountToLiquidate, + false + ); + await expect( + pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [dai.address], + [amountToLiquidate], + [0], + borrower.address, + params, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + }); + + it('Revert if debt asset amount to liquidate is greater than requested flash loan', async () => { + await depositAndHFBelowOne(); + + const { dai, weth, users, pool, helpersContract, flashLiquidationAdapter } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + const expectedSwap = ethers.utils.parseEther('0.4'); + + // Set how much ETH will be sold and swapped for DAI at Uniswap mock + await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); + + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2); + + // Correct params + const params = buildFlashLiquidationAdapterParams( + weth.address, + dai.address, + borrower.address, + amountToLiquidate.toString(), + false + ); + // Bad flash loan params: requested DAI amount below amountToLiquidate + await expect( + pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [dai.address], + [amountToLiquidate.div(2).toString()], + [0], + borrower.address, + params, + 0 + ) + ).to.be.revertedWith('FLASH_COVER_NOT_ENOUGH'); + }); + + it('Revert if requested multiple assets', async () => { + await depositAndHFBelowOne(); + + const { dai, weth, users, pool, helpersContract, flashLiquidationAdapter } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + const expectedSwap = ethers.utils.parseEther('0.4'); + + // Set how much ETH will be sold and swapped for DAI at Uniswap mock + await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); + + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2); + + // Correct params + const params = buildFlashLiquidationAdapterParams( + weth.address, + dai.address, + borrower.address, + amountToLiquidate.toString(), + false + ); + // Bad flash loan params: requested multiple assets + await expect( + pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [dai.address, weth.address], + [10, 10], + [0], + borrower.address, + params, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); }); }); }); From 97a6179703f2c697a57fe50a12080bcd566cfcc4 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Tue, 19 Jan 2021 20:58:21 -0500 Subject: [PATCH 024/219] Added all UNI-V2 pairs and configs --- helpers/contracts-helpers.ts | 2 +- helpers/types.ts | 32 +++- markets/aave/commons.ts | 16 +- markets/uniswap/commons.ts | 114 ++++++++++++-- markets/uniswap/index.ts | 75 ++++++---- markets/uniswap/reservesConfigs.ts | 230 +++++++++++++++++++++++++++-- 6 files changed, 404 insertions(+), 65 deletions(-) diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 4b6a2830..8c2e8e58 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -16,7 +16,7 @@ import { MintableERC20 } from '../types/MintableERC20'; import { Artifact } from 'hardhat/types'; import { Artifact as BuidlerArtifact } from '@nomiclabs/buidler/types'; import { verifyContract } from './etherscan-verification'; -import { getIErc20Detailed, getFirstSigner } from './contracts-getters'; +import { getIErc20Detailed } from './contracts-getters'; import { addGas, totalGas } from '../gas-tracker'; export type MockTokenMap = { [symbol: string]: MintableERC20 }; diff --git a/helpers/types.ts b/helpers/types.ts index 55113100..0a2b7194 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -206,8 +206,20 @@ export interface iAssetBase { UniDAI: T; UniUSDC: T; UniUSDT: T; - UniWETHDAI: T; - UniWETHWBTC: T; + UniDAIWETH: T; + UniWBTCWETH: T; + UniAAVEWETH: T; + UniBATWETH: T; + UniUSDCDAI: T; + UniCRVWETH: T; + UniLINKWETH: T; + UniMKRWETH: T; + UniRENWETH: T; + UniSNXWETH: T; + UniUNIWETH: T; + UniUSDCWETH: T; + UniWBTCUSDC: T; + UniYFIWETH: T; } export type iAssetsWithoutETH = Omit, 'ETH'>; @@ -245,8 +257,20 @@ export type iUniswapPoolAssets = Pick< | 'UniUSDT' | 'UniWBTC' | 'UniWETH' - | 'UniWETHDAI' - | 'UniWETHWBTC' + | 'UniDAIWETH' + | 'UniWBTCWETH' + | 'UniAAVEWETH' + | 'UniBATWETH' + | 'UniUSDCDAI' + | 'UniCRVWETH' + | 'UniLINKWETH' + | 'UniMKRWETH' + | 'UniRENWETH' + | 'UniSNXWETH' + | 'UniUNIWETH' + | 'UniUSDCWETH' + | 'UniWBTCUSDC' + | 'UniYFIWETH' >; export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index 1d4b1e4a..beb0c88a 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -28,8 +28,20 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), UniWBTC: oneEther.multipliedBy('47.332685').toFixed(), UniWETH: oneEther.toFixed(), - UniWETHDAI: oneEther.multipliedBy('22.407436').toFixed(), - UniWETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), + UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniAAVEWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), + UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniLINKWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), + UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; // ---------------- diff --git a/markets/uniswap/commons.ts b/markets/uniswap/commons.ts index db06cfa0..0aa7b4bc 100644 --- a/markets/uniswap/commons.ts +++ b/markets/uniswap/commons.ts @@ -28,8 +28,20 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), UniWBTC: oneEther.multipliedBy('47.332685').toFixed(), UniWETH: oneEther.toFixed(), - UniWETHDAI: oneEther.multipliedBy('22.407436').toFixed(), - UniWETHWBTC: oneEther.multipliedBy('22.407436').toFixed(), + UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniAAVEWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), + UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniLINKWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), + UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; // ---------------- @@ -74,10 +86,46 @@ export const CommonsConfig: ICommonConfiguration = { UniWBTC: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - UniWETHDAI: { + UniDAIWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniWETHWBTC: { + UniWBTCWETH: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + UniAAVEWETH:{ + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + UniBATWETH: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + UniUSDCDAI: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + UniCRVWETH: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + UniLINKWETH: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + UniMKRWETH: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + UniRENWETH: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + UniSNXWETH: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + UniUNIWETH: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + UniUSDCWETH: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + UniWBTCUSDC: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + UniYFIWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, }, @@ -166,13 +214,25 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.buidlerevm]: {}, [EthereumNetwork.kovan]: { - UniUSDT: ZERO_ADDRESS, - UniWBTC: ZERO_ADDRESS, - UniUSDC: ZERO_ADDRESS, - UniDAI:ZERO_ADDRESS, - UniWETHDAI: ZERO_ADDRESS, - UniWETHWBTC: ZERO_ADDRESS, - USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + UniUSDT: '0x0bF499444525a23E7Bb61997539725cA2e928138', + UniWBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', + UniUSDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', + UniDAI:'0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', + UniDAIWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', // Mock oracles + UniWBTCWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniAAVEWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniBATWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniUSDCDAI: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniCRVWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniLINKWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniMKRWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniRENWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniSNXWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniUNIWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniUSDCWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniWBTCUSDC: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + UniYFIWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [EthereumNetwork.ropsten]: { }, @@ -181,8 +241,20 @@ export const CommonsConfig: ICommonConfiguration = { UniWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', UniUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', UniDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', - UniWETHDAI: ZERO_ADDRESS, - UniWETHWBTC: ZERO_ADDRESS, + UniDAIWETH: ZERO_ADDRESS, + UniWBTCWETH: ZERO_ADDRESS, + UniAAVEWETH: ZERO_ADDRESS, + UniBATWETH: ZERO_ADDRESS, + UniUSDCDAI: ZERO_ADDRESS, + UniCRVWETH: ZERO_ADDRESS, + UniLINKWETH: ZERO_ADDRESS, + UniMKRWETH: ZERO_ADDRESS, + UniRENWETH: ZERO_ADDRESS, + UniSNXWETH: ZERO_ADDRESS, + UniUNIWETH: ZERO_ADDRESS, + UniUSDCWETH: ZERO_ADDRESS, + UniWBTCUSDC: ZERO_ADDRESS, + UniYFIWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [EthereumNetwork.tenderlyMain]: { @@ -190,8 +262,20 @@ export const CommonsConfig: ICommonConfiguration = { UniWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', UniUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', UniDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', - UniWETHDAI: ZERO_ADDRESS, - UniWETHWBTC: ZERO_ADDRESS, + UniDAIWETH: ZERO_ADDRESS, + UniWBTCWETH: ZERO_ADDRESS, + UniAAVEWETH: ZERO_ADDRESS, + UniBATWETH: ZERO_ADDRESS, + UniUSDCDAI: ZERO_ADDRESS, + UniCRVWETH: ZERO_ADDRESS, + UniLINKWETH: ZERO_ADDRESS, + UniMKRWETH: ZERO_ADDRESS, + UniRENWETH: ZERO_ADDRESS, + UniSNXWETH: ZERO_ADDRESS, + UniUNIWETH: ZERO_ADDRESS, + UniUSDCWETH: ZERO_ADDRESS, + UniWBTCUSDC: ZERO_ADDRESS, + UniYFIWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, }, diff --git a/markets/uniswap/index.ts b/markets/uniswap/index.ts index 0447ca15..55a5a15d 100644 --- a/markets/uniswap/index.ts +++ b/markets/uniswap/index.ts @@ -8,8 +8,20 @@ import { strategyUSDT, strategyWETH, strategyWBTC, - strategyWETHWBTC, - strategyWETHDAI + strategyWBTCWETH, + strategyDAIWETH, + strategyAAVEWETH, + strategyBATWETH, + strategyUSDCDAI, + strategyCRVWETH, + strategyLINKWETH, + strategyMKRWETH, + strategyRENWETH, + strategySNXWETH, + strategyUNIWETH, + strategyUSDCWETH, + strategyWBTCUSDC, + strategyYFIWETH, } from './reservesConfigs'; // ---------------- @@ -26,8 +38,20 @@ export const UniswapConfig: IUniswapConfiguration = { UniUSDC: strategyUSDC, UniUSDT: strategyUSDT, UniWBTC: strategyWBTC, - UniWETHDAI: strategyWETHDAI, - UniWETHWBTC: strategyWETHWBTC + UniDAIWETH: strategyDAIWETH, + UniWBTCWETH: strategyWBTCWETH, + UniAAVEWETH: strategyAAVEWETH, + UniBATWETH: strategyBATWETH, + UniUSDCDAI: strategyUSDCDAI, + UniCRVWETH: strategyCRVWETH, + UniLINKWETH: strategyLINKWETH, + UniMKRWETH: strategyMKRWETH, + UniRENWETH: strategyRENWETH, + UniSNXWETH: strategySNXWETH, + UniUNIWETH: strategyUNIWETH, + UniUSDCWETH: strategyUSDCWETH, + UniWBTCUSDC: strategyWBTCUSDC, + UniYFIWETH: strategyYFIWETH, }, ReserveAssets: { [eEthereumNetwork.buidlerevm]: {}, @@ -39,30 +63,11 @@ export const UniswapConfig: IUniswapConfiguration = { UniUSDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', UniWBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', UniWETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', - UniWETHDAI: '0x7d3A67ab574abD3F9849e5fcDa48c19939d032b4', - uniWETHWBTC: '0x342e78bf229Cd2a750E80D7D7c2C185455979b91', + UniDAIWETH: '0x7d3A67ab574abD3F9849e5fcDa48c19939d032b4', + uniWBTCWETH: '0x342e78bf229Cd2a750E80D7D7c2C185455979b91', + // Other assets }, [EthereumNetwork.ropsten]: { - // AAVE: '', - // BAT: '0x85B24b3517E3aC7bf72a14516160541A60cFF19d', - // BUSD: '0xFA6adcFf6A90c11f31Bc9bb59eC0a6efB38381C6', - // DAI: '0xf80A32A835F79D7787E8a8ee5721D0fEaFd78108', - // ENJ: ZERO_ADDRESS, - // KNC: '0xCe4aA1dE3091033Ba74FA2Ad951f6adc5E5cF361', - // LINK: '0x1a906E71FF9e28d8E01460639EB8CF0a6f0e2486', - // MANA: '0x78b1F763857C8645E46eAdD9540882905ff32Db7', - // MKR: '0x2eA9df3bABe04451c9C3B06a2c844587c59d9C37', - // REN: ZERO_ADDRESS, - // SNX: '0xF80Aa7e2Fda4DA065C55B8061767F729dA1476c7', - // SUSD: '0xc374eB17f665914c714Ac4cdC8AF3a3474228cc5', - // TUSD: '0xa2EA00Df6d8594DBc76b79beFe22db9043b8896F', - // UNI: ZERO_ADDRESS, - // USDC: '0x851dEf71f0e6A903375C1e536Bd9ff1684BAD802', - // USDT: '0xB404c51BBC10dcBE948077F18a4B8E553D160084', - // WBTC: '0xa0E54Ab6AA5f0bf1D62EC3526436F3c05b3348A0', - // WETH: '0xc778417e063141139fce010982780140aa0cd5ab', - // YFI: ZERO_ADDRESS, - // ZRX: '0x02d7055704EfF050323A2E5ee4ba05DB2A588959', }, [EthereumNetwork.main]: { UniDAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', @@ -70,8 +75,20 @@ export const UniswapConfig: IUniswapConfiguration = { UniUSDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', UniWBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', UniWETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - UniWETHDAI: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', - UniWETHWBTC: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', + UniDAIWETH: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', + UniWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', + UniAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f', + UniBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838', + UniUSDCDAI: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', + UniCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE', + UniLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974', + UniMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225', + UniRENWETH: '0x8Bd1661Da98EBDd3BD080F0bE4e6d9bE8cE9858c', + UniSNXWETH: '0x43AE24960e5534731Fc831386c07755A2dc33D47', + UniUNIWETH: '0xd3d2E2692501A5c9Ca623199D38826e513033a17', + UniUSDCWETH: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc', + UniWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416', + UniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', }, [EthereumNetwork.tenderlyMain]: { DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', @@ -79,8 +96,6 @@ export const UniswapConfig: IUniswapConfiguration = { USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - WETHDAI: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', - WETHWBTC: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', }, }, }; diff --git a/markets/uniswap/reservesConfigs.ts b/markets/uniswap/reservesConfigs.ts index caeaba46..aed62b2d 100644 --- a/markets/uniswap/reservesConfigs.ts +++ b/markets/uniswap/reservesConfigs.ts @@ -87,24 +87,92 @@ export const strategyUSDT: IReserveParams = { reserveFactor: '1000' }; -export const strategyWETHDAI: IReserveParams = { +export const strategyDAIWETH: IReserveParams = { optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: '0', variableRateSlope1: '0', variableRateSlope2: '0', stableRateSlope1: '0', stableRateSlope2: '0', - baseLTVAsCollateral: '5000', - liquidationThreshold: '6500', - liquidationBonus: '11000', - borrowingEnabled: true, - stableBorrowRateEnabled: true, + baseLTVAsCollateral: '6000', + liquidationThreshold: '7000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '0' }; -export const strategyWETHWBTC: IReserveParams = { +export const strategyWBTCWETH: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '6000', + liquidationThreshold: '7000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0' +}; + +export const strategyAAVEWETH: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '6000', + liquidationThreshold: '7000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0' +}; + +export const strategyBATWETH: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '6000', + liquidationThreshold: '7000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0' +}; + +export const strategyUSDCDAI: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '6000', + liquidationThreshold: '7000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0' +}; + +export const strategyCRVWETH: IReserveParams = { optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: '0', variableRateSlope1: '0', @@ -112,11 +180,147 @@ export const strategyWETHWBTC: IReserveParams = { stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '5000', - liquidationThreshold: '6500', - liquidationBonus: '11000', - borrowingEnabled: true, - stableBorrowRateEnabled: true, + liquidationThreshold: '6000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '0' +}; + +export const strategyLINKWETH: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '6000', + liquidationThreshold: '7000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0' +}; + +export const strategyMKRWETH: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '6000', + liquidationThreshold: '7000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0' +}; + +export const strategyRENWETH: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '6000', + liquidationThreshold: '7000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0' +}; + +export const strategySNXWETH: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '4000', + liquidationThreshold: '6000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0' +}; + +export const strategyUNIWETH: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '6000', + liquidationThreshold: '7000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0' +}; + +export const strategyUSDCWETH: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '6000', + liquidationThreshold: '7000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0' +}; + +export const strategyWBTCUSDC: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '6000', + liquidationThreshold: '7000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0' +}; + +export const strategyYFIWETH: IReserveParams = { + optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseLTVAsCollateral: '5000', + liquidationThreshold: '6000', + liquidationBonus: '11500', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0' }; \ No newline at end of file From c7a8f41d46620511392be89559e445dba3c030bf Mon Sep 17 00:00:00 2001 From: David Racero Date: Thu, 21 Jan 2021 00:42:39 +0100 Subject: [PATCH 025/219] Added test fixes to support latest stable fix --- package.json | 2 +- .../scenarios/borrow-repay-stable.json | 9 ++ test/helpers/scenarios/credit-delegation.json | 30 ++++- .../scenarios/rebalance-stable-rate.json | 111 +++++------------- test/mainnet/check-list.spec.ts | 92 ++++++++------- test/scenario.spec.ts | 16 +-- test/uniswapAdapters.repay.spec.ts | 16 +-- test/weth-gateway.spec.ts | 108 ++++++++++------- 8 files changed, 194 insertions(+), 190 deletions(-) diff --git a/package.json b/package.json index 4fefea1b..7ea71aea 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "compile": "SKIP_LOAD=true hardhat compile", "console:fork": "MAINNET_FORK=true hardhat console", "test": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test/*.spec.ts", - "test-scenarios": "npm run test -- test/__setup.spec.ts test/scenario.spec.ts", + "test-scenarios": "npx hardhat test test/__setup.spec.ts test/scenario.spec.ts", "test-repay-with-collateral": "hardhat test test/__setup.spec.ts test/repay-with-collateral.spec.ts", "test-liquidate-with-collateral": "hardhat test test/__setup.spec.ts test/flash-liquidation-with-collateral.spec.ts", "test-liquidate-underlying": "hardhat test test/__setup.spec.ts test/liquidation-underlying.spec.ts", diff --git a/test/helpers/scenarios/borrow-repay-stable.json b/test/helpers/scenarios/borrow-repay-stable.json index 87e7de0b..3f472387 100644 --- a/test/helpers/scenarios/borrow-repay-stable.json +++ b/test/helpers/scenarios/borrow-repay-stable.json @@ -208,6 +208,15 @@ }, "expected": "revert", "revertMessage": "The collateral balance is 0" + }, + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" } ] }, diff --git a/test/helpers/scenarios/credit-delegation.json b/test/helpers/scenarios/credit-delegation.json index a0aecf1b..0d15d7f1 100644 --- a/test/helpers/scenarios/credit-delegation.json +++ b/test/helpers/scenarios/credit-delegation.json @@ -10,7 +10,7 @@ "args": { "reserve": "WETH", "amount": "1000", - "user": "0" + "user": "3" }, "expected": "success" }, @@ -18,7 +18,7 @@ "name": "approve", "args": { "reserve": "WETH", - "user": "0" + "user": "3" }, "expected": "success" }, @@ -27,6 +27,32 @@ "args": { "reserve": "WETH", "amount": "1000", + "user": "3" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", "user": "0" }, "expected": "success" diff --git a/test/helpers/scenarios/rebalance-stable-rate.json b/test/helpers/scenarios/rebalance-stable-rate.json index 70ea820a..8c7e6c19 100644 --- a/test/helpers/scenarios/rebalance-stable-rate.json +++ b/test/helpers/scenarios/rebalance-stable-rate.json @@ -8,7 +8,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "DAI", + "reserve": "USDC", "user": "0", "target": "1", "borrowRateMode": "variable" @@ -19,12 +19,12 @@ ] }, { - "description": "User 0 deposits 1000 DAI, user 1 deposits 5 ETH, borrows 600 DAI at a variable rate, user 0 rebalances user 1 (revert expected)", + "description": "User 0 deposits 1000 USDC, user 1 deposits 5 ETH, borrows 600 DAI at a variable rate, user 0 rebalances user 1 (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "DAI", + "reserve": "USDC", "amount": "1000", "user": "0" }, @@ -33,7 +33,7 @@ { "name": "approve", "args": { - "reserve": "DAI", + "reserve": "USDC", "user": "0" }, "expected": "success" @@ -41,7 +41,7 @@ { "name": "deposit", "args": { - "reserve": "DAI", + "reserve": "USDC", "amount": "1000", "user": "0" }, @@ -51,7 +51,7 @@ "name": "mint", "args": { "reserve": "WETH", - "amount": "5", + "amount": "7", "user": "1" }, "expected": "success" @@ -69,7 +69,7 @@ "args": { "reserve": "WETH", - "amount": "5", + "amount": "7", "user": "1" }, "expected": "success" @@ -77,18 +77,17 @@ { "name": "borrow", "args": { - "reserve": "DAI", + "reserve": "USDC", "amount": "250", "borrowRateMode": "stable", - "user": "1", - "timeTravel": "365" + "user": "1" }, "expected": "success" }, { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "DAI", + "reserve": "USDC", "user": "0", "target": "1" }, @@ -103,18 +102,17 @@ { "name": "borrow", "args": { - "reserve": "DAI", + "reserve": "USDC", "amount": "200", - "borrowRateMode": "stable", - "user": "1", - "timeTravel": "365" + "borrowRateMode": "variable", + "user": "1" }, "expected": "success" }, { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "DAI", + "reserve": "USDC", "user": "0", "target": "1" }, @@ -129,18 +127,17 @@ { "name": "borrow", "args": { - "reserve": "DAI", + "reserve": "USDC", "amount": "200", - "borrowRateMode": "stable", - "user": "1", - "timeTravel": "365" + "borrowRateMode": "variable", + "user": "1" }, "expected": "success" }, { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "DAI", + "reserve": "USDC", "user": "0", "target": "1" }, @@ -155,18 +152,17 @@ { "name": "borrow", "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "stable", - "user": "1", - "timeTravel": "365" + "reserve": "USDC", + "amount": "280", + "borrowRateMode": "variable", + "user": "1" }, "expected": "success" }, { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "DAI", + "reserve": "USDC", "user": "0", "target": "1" }, @@ -175,75 +171,24 @@ } ] }, - { - "description": "User 2 deposits ETH and borrows the remaining DAI, causing the stable rates to rise (usage ratio = 94%). User 0 tries to rebalance user 1 (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "5", - "user": "2" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "2" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "5", - "user": "2" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "190", - "borrowRateMode": "variable", - "user": "2" - }, - "expected": "success" - }, - { - "name": "rebalanceStableBorrowRate", - "args": { - "reserve": "DAI", - "user": "0", - "target": "1" - }, - "expected": "revert", - "revertMessage": "Interest rate rebalance conditions were not met" - } - ] - }, { - "description": "User 2 borrows the remaining DAI (usage ratio = 100%). User 0 rebalances user 1", + "description": "User 0 borrows the remaining USDC (usage ratio = 100%). User 0 rebalances user 1", "actions": [ { "name": "borrow", "args": { - "reserve": "DAI", - "amount": "60", + "reserve": "USDC", + "amount": "20", "borrowRateMode": "variable", - "user": "2" + "user": "1" }, "expected": "success" }, { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "DAI", + "reserve": "USDC", "user": "0", "target": "1" }, diff --git a/test/mainnet/check-list.spec.ts b/test/mainnet/check-list.spec.ts index 08416eda..b6b30bc1 100644 --- a/test/mainnet/check-list.spec.ts +++ b/test/mainnet/check-list.spec.ts @@ -1,28 +1,28 @@ -import {MAX_UINT_AMOUNT} from '../../helpers/constants'; -import {convertToCurrencyDecimals} from '../../helpers/contracts-helpers'; -import {makeSuite, TestEnv} from '../helpers/make-suite'; -import {parseEther} from 'ethers/lib/utils'; -import {DRE, waitForTx} from '../../helpers/misc-utils'; -import {BigNumber} from 'ethers'; -import {getStableDebtToken, getVariableDebtToken} from '../../helpers/contracts-getters'; -import {deploySelfdestructTransferMock} from '../../helpers/contracts-deployments'; -import {IUniswapV2Router02Factory} from '../../types/IUniswapV2Router02Factory'; +import { MAX_UINT_AMOUNT } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { makeSuite, TestEnv } from '../helpers/make-suite'; +import { parseEther } from 'ethers/lib/utils'; +import { DRE, waitForTx } from '../../helpers/misc-utils'; +import { BigNumber } from 'ethers'; +import { getStableDebtToken, getVariableDebtToken } from '../../helpers/contracts-getters'; +import { deploySelfdestructTransferMock } from '../../helpers/contracts-deployments'; +import { IUniswapV2Router02Factory } from '../../types/IUniswapV2Router02Factory'; -const {expect} = require('chai'); +const { expect } = require('chai'); const UNISWAP_ROUTER = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'; makeSuite('Mainnet Check list', (testEnv: TestEnv) => { const zero = BigNumber.from('0'); const depositSize = parseEther('5'); - + const daiSize = parseEther('10000'); it('Deposit WETH', async () => { - const {users, wethGateway, aWETH, pool} = testEnv; + const { users, wethGateway, aWETH, pool } = testEnv; const user = users[1]; // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -31,7 +31,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Withdraw WETH - Partial', async () => { - const {users, wethGateway, aWETH, pool} = testEnv; + const { users, wethGateway, aWETH, pool } = testEnv; const user = users[1]; const priorEthersBalance = await user.signer.getBalance(); @@ -46,10 +46,10 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { const approveTx = await aWETH .connect(user.signer) .approve(wethGateway.address, MAX_UINT_AMOUNT); - const {gasUsed: approveGas} = await waitForTx(approveTx); + const { gasUsed: approveGas } = await waitForTx(approveTx); // Partial Withdraw and send native Ether to user - const {gasUsed: withdrawGas} = await waitForTx( + const { gasUsed: withdrawGas } = await waitForTx( await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) ); @@ -68,7 +68,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Withdraw WETH - Full', async () => { - const {users, aWETH, wethGateway, pool} = testEnv; + const { users, aWETH, wethGateway, pool } = testEnv; const user = users[1]; const priorEthersBalance = await user.signer.getBalance(); @@ -80,10 +80,10 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { const approveTx = await aWETH .connect(user.signer) .approve(wethGateway.address, MAX_UINT_AMOUNT); - const {gasUsed: approveGas} = await waitForTx(approveTx); + const { gasUsed: approveGas } = await waitForTx(approveTx); // Full withdraw - const {gasUsed: withdrawGas} = await waitForTx( + const { gasUsed: withdrawGas } = await waitForTx( await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) ); @@ -99,22 +99,26 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Borrow stable WETH and Full Repay with ETH', async () => { - const {users, wethGateway, aWETH, weth, pool, helpersContract} = testEnv; + const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; const borrowSize = parseEther('1'); const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); const user = users[1]; - const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address); + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); const stableDebtToken = await getStableDebtToken(stableDebtTokenAddress); - // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + // Deposit 10000 DAI + await dai.connect(user.signer).mint(daiSize); + await dai.connect(user.signer).approve(pool.address, daiSize); + await pool.connect(user.signer).deposit(dai.address, daiSize, user.address, '0'); - const aTokensBalance = await aWETH.balanceOf(user.address); + const aTokensBalance = await aDai.balanceOf(user.address); expect(aTokensBalance).to.be.gt(zero); - expect(aTokensBalance).to.be.gte(depositSize); + expect(aTokensBalance).to.be.gte(daiSize); // Borrow WETH with WETH as collateral await waitForTx( @@ -129,7 +133,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '1', user.address, {value: repaySize}) + .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) ); const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); @@ -137,19 +141,19 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Borrow variable WETH and Full Repay with ETH', async () => { - const {users, wethGateway, aWETH, weth, pool, helpersContract} = testEnv; + const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; const borrowSize = parseEther('1'); const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); const user = users[1]; - const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address ); const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -170,7 +174,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { await waitForTx( await wethGateway .connect(user.signer) - .repayETH(partialPayment, '2', user.address, {value: partialPayment}) + .repayETH(partialPayment, '2', user.address, { value: partialPayment }) ); const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); @@ -180,17 +184,17 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, {value: repaySize}) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); }); it('Borrow ETH via delegateApprove ETH and repays back', async () => { - const {users, wethGateway, aWETH, weth, helpersContract} = testEnv; + const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; const borrowSize = parseEther('1'); const user = users[2]; - const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address ); const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); @@ -199,7 +203,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { expect(priorDebtBalance).to.be.eq(zero); // Deposit WETH with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -222,14 +226,14 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, {value: borrowSize.mul(2)}) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); }); it('Should revert if receiver function receives Ether if not WETH', async () => { - const {users, wethGateway} = testEnv; + const { users, wethGateway } = testEnv; const user = users[0]; const amount = parseEther('1'); @@ -244,7 +248,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Should revert if fallback functions is called with Ether', async () => { - const {users, wethGateway} = testEnv; + const { users, wethGateway } = testEnv; const user = users[0]; const amount = parseEther('1'); const fakeABI = ['function wantToCallFallback()']; @@ -263,7 +267,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Should revert if fallback functions is called', async () => { - const {users, wethGateway} = testEnv; + const { users, wethGateway } = testEnv; const user = users[0]; const fakeABI = ['function wantToCallFallback()']; @@ -281,7 +285,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Getters should retrieve correct state', async () => { - const {aWETH, weth, pool, wethGateway} = testEnv; + const { aWETH, weth, pool, wethGateway } = testEnv; const WETHAddress = await wethGateway.getWETHAddress(); const aWETHAddress = await wethGateway.getAWETHAddress(); @@ -293,7 +297,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Owner can do emergency token recovery', async () => { - const {users, weth, dai, wethGateway, deployer} = testEnv; + const { users, weth, dai, wethGateway, deployer } = testEnv; const user = users[0]; const amount = parseEther('1'); @@ -328,7 +332,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Owner can do emergency native ETH recovery', async () => { - const {users, wethGateway, deployer} = testEnv; + const { users, wethGateway, deployer } = testEnv; const user = users[0]; const amount = parseEther('1'); const userBalancePriorCall = await user.signer.getBalance(); @@ -339,13 +343,13 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { // Selfdestruct the mock, pointing to WETHGateway address const callTx = await selfdestructContract .connect(user.signer) - .destroyAndTransfer(wethGateway.address, {value: amount}); - const {gasUsed} = await waitForTx(callTx); + .destroyAndTransfer(wethGateway.address, { value: amount }); + const { gasUsed } = await waitForTx(callTx); const gasFees = gasUsed.mul(callTx.gasPrice); const userBalanceAfterCall = await user.signer.getBalance(); expect(userBalanceAfterCall).to.be.eq(userBalancePriorCall.sub(amount).sub(gasFees), ''); - 'User should have lost the funds'; + ('User should have lost the funds'); // Recover the funds from the contract and sends back to the user await wethGateway.connect(deployer.signer).emergencyEtherTransfer(user.address, amount); diff --git a/test/scenario.spec.ts b/test/scenario.spec.ts index 50793c0c..13037cfb 100644 --- a/test/scenario.spec.ts +++ b/test/scenario.spec.ts @@ -1,12 +1,12 @@ -import {configuration as actionsConfiguration} from './helpers/actions'; -import {configuration as calculationsConfiguration} from './helpers/utils/calculations'; +import { configuration as actionsConfiguration } from './helpers/actions'; +import { configuration as calculationsConfiguration } from './helpers/utils/calculations'; import fs from 'fs'; import BigNumber from 'bignumber.js'; -import {makeSuite} from './helpers/make-suite'; -import {getReservesConfigByPool} from '../helpers/configuration'; -import {AavePools, iAavePoolAssets, IReserveParams} from '../helpers/types'; -import {executeStory} from './helpers/scenario-engine'; +import { makeSuite } from './helpers/make-suite'; +import { getReservesConfigByPool } from '../helpers/configuration'; +import { AavePools, iAavePoolAssets, IReserveParams } from '../helpers/types'; +import { executeStory } from './helpers/scenario-engine'; const scenarioFolder = './test/helpers/scenarios/'; @@ -20,7 +20,7 @@ fs.readdirSync(scenarioFolder).forEach((file) => { makeSuite(scenario.title, async (testEnv) => { before('Initializing configuration', async () => { // Sets BigNumber for this suite, instead of globally - BigNumber.config({DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN}); + BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage @@ -30,7 +30,7 @@ fs.readdirSync(scenarioFolder).forEach((file) => { }); after('Reset', () => { // Reset BigNumber - BigNumber.config({DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP}); + BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); }); for (const story of scenario.stories) { diff --git a/test/uniswapAdapters.repay.spec.ts b/test/uniswapAdapters.repay.spec.ts index b79409de..27f91e02 100644 --- a/test/uniswapAdapters.repay.spec.ts +++ b/test/uniswapAdapters.repay.spec.ts @@ -803,15 +803,15 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { const userAddress = users[0].address; // Add deposit for user - await dai.mint(parseEther('20')); - await dai.approve(pool.address, parseEther('20')); - await pool.deposit(dai.address, parseEther('20'), userAddress, 0); + await dai.mint(parseEther('30')); + await dai.approve(pool.address, parseEther('30')); + await pool.deposit(dai.address, parseEther('30'), userAddress, 0); const amountCollateralToSwap = parseEther('10'); const debtAmount = parseEther('10'); // Open user Debt - await pool.connect(user).borrow(dai.address, debtAmount, 1, 0, userAddress); + await pool.connect(user).borrow(dai.address, debtAmount, 2, 0, userAddress); const daiStableDebtTokenAddress = ( await helpersContract.getReserveTokensAddresses(dai.address) @@ -1376,16 +1376,16 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { const userAddress = users[0].address; // Add deposit for user - await dai.mint(parseEther('20')); - await dai.approve(pool.address, parseEther('20')); - await pool.deposit(dai.address, parseEther('20'), userAddress, 0); + await dai.mint(parseEther('30')); + await dai.approve(pool.address, parseEther('30')); + await pool.deposit(dai.address, parseEther('30'), userAddress, 0); const amountCollateralToSwap = parseEther('4'); const debtAmount = parseEther('3'); // Open user Debt - await pool.connect(user).borrow(dai.address, debtAmount, 1, 0, userAddress); + await pool.connect(user).borrow(dai.address, debtAmount, 2, 0, userAddress); const daiStableDebtTokenAddress = ( await helpersContract.getReserveTokensAddresses(dai.address) diff --git a/test/weth-gateway.spec.ts b/test/weth-gateway.spec.ts index 20393b85..1b3f93ea 100644 --- a/test/weth-gateway.spec.ts +++ b/test/weth-gateway.spec.ts @@ -1,25 +1,31 @@ -import {MAX_UINT_AMOUNT} from '../helpers/constants'; -import {convertToCurrencyDecimals} from '../helpers/contracts-helpers'; -import {makeSuite, TestEnv} from './helpers/make-suite'; -import {parseEther} from 'ethers/lib/utils'; -import {DRE, waitForTx} from '../helpers/misc-utils'; -import {BigNumber} from 'ethers'; -import {getStableDebtToken, getVariableDebtToken} from '../helpers/contracts-getters'; -import {deploySelfdestructTransferMock} from '../helpers/contracts-deployments'; +import { MAX_UINT_AMOUNT } from '../helpers/constants'; +import { convertToCurrencyDecimals } from '../helpers/contracts-helpers'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { parseEther } from 'ethers/lib/utils'; +import { DRE, waitForTx } from '../helpers/misc-utils'; +import { BigNumber } from 'ethers'; +import { getStableDebtToken, getVariableDebtToken } from '../helpers/contracts-getters'; +import { deploySelfdestructTransferMock } from '../helpers/contracts-deployments'; -const {expect} = require('chai'); +const { expect } = require('chai'); makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => { const zero = BigNumber.from('0'); const depositSize = parseEther('5'); - - it('Deposit WETH', async () => { - const {users, wethGateway, aWETH, pool} = testEnv; + const daiSize = parseEther('10000'); + it('Deposit WETH via WethGateway and DAI', async () => { + const { users, wethGateway, aWETH, dai, pool } = testEnv; const user = users[1]; + const depositor = users[0]; + + // Deposit liquidity with native ETH + await wethGateway + .connect(depositor.signer) + .depositETH(depositor.address, '0', { value: depositSize }); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -28,7 +34,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Withdraw WETH - Partial', async () => { - const {users, wethGateway, aWETH, pool} = testEnv; + const { users, wethGateway, aWETH, pool } = testEnv; const user = users[1]; const priorEthersBalance = await user.signer.getBalance(); @@ -43,10 +49,10 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => const approveTx = await aWETH .connect(user.signer) .approve(wethGateway.address, MAX_UINT_AMOUNT); - const {gasUsed: approveGas} = await waitForTx(approveTx); + const { gasUsed: approveGas } = await waitForTx(approveTx); // Partial Withdraw and send native Ether to user - const {gasUsed: withdrawGas} = await waitForTx( + const { gasUsed: withdrawGas } = await waitForTx( await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) ); @@ -65,7 +71,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Withdraw WETH - Full', async () => { - const {users, aWETH, wethGateway, pool} = testEnv; + const { users, aWETH, wethGateway, pool } = testEnv; const user = users[1]; const priorEthersBalance = await user.signer.getBalance(); @@ -77,10 +83,10 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => const approveTx = await aWETH .connect(user.signer) .approve(wethGateway.address, MAX_UINT_AMOUNT); - const {gasUsed: approveGas} = await waitForTx(approveTx); + const { gasUsed: approveGas } = await waitForTx(approveTx); // Full withdraw - const {gasUsed: withdrawGas} = await waitForTx( + const { gasUsed: withdrawGas } = await waitForTx( await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) ); @@ -96,22 +102,32 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Borrow stable WETH and Full Repay with ETH', async () => { - const {users, wethGateway, aWETH, weth, pool, helpersContract} = testEnv; + const { users, wethGateway, aDai, weth, dai, pool, helpersContract } = testEnv; const borrowSize = parseEther('1'); const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); const user = users[1]; + const depositor = users[0]; - const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address); + // Deposit with native ETH + await wethGateway + .connect(depositor.signer) + .depositETH(depositor.address, '0', { value: depositSize }); + + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); const stableDebtToken = await getStableDebtToken(stableDebtTokenAddress); - // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + // Deposit 10000 DAI + await dai.connect(user.signer).mint(daiSize); + await dai.connect(user.signer).approve(pool.address, daiSize); + await pool.connect(user.signer).deposit(dai.address, daiSize, user.address, '0'); - const aTokensBalance = await aWETH.balanceOf(user.address); + const aTokensBalance = await aDai.balanceOf(user.address); expect(aTokensBalance).to.be.gt(zero); - expect(aTokensBalance).to.be.gte(depositSize); + expect(aTokensBalance).to.be.gte(daiSize); // Borrow WETH with WETH as collateral await waitForTx( @@ -126,27 +142,31 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '1', user.address, {value: repaySize}) + .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) ); const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); expect(debtBalanceAfterRepay).to.be.eq(zero); + + // Withdraw DAI + await aDai.connect(user.signer).approve(pool.address, MAX_UINT_AMOUNT); + await pool.connect(user.signer).withdraw(dai.address, MAX_UINT_AMOUNT, user.address); }); it('Borrow variable WETH and Full Repay with ETH', async () => { - const {users, wethGateway, aWETH, weth, pool, helpersContract} = testEnv; + const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; const borrowSize = parseEther('1'); const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); const user = users[1]; - const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address ); const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -167,7 +187,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(partialPayment, '2', user.address, {value: partialPayment}) + .repayETH(partialPayment, '2', user.address, { value: partialPayment }) ); const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); @@ -177,17 +197,17 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, {value: repaySize}) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); }); it('Borrow ETH via delegateApprove ETH and repays back', async () => { - const {users, wethGateway, aWETH, weth, helpersContract} = testEnv; + const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; const borrowSize = parseEther('1'); const user = users[2]; - const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address ); const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); @@ -196,7 +216,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => expect(priorDebtBalance).to.be.eq(zero); // Deposit WETH with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -219,14 +239,14 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, {value: borrowSize.mul(2)}) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); }); it('Should revert if receiver function receives Ether if not WETH', async () => { - const {users, wethGateway} = testEnv; + const { users, wethGateway } = testEnv; const user = users[0]; const amount = parseEther('1'); @@ -241,7 +261,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Should revert if fallback functions is called with Ether', async () => { - const {users, wethGateway} = testEnv; + const { users, wethGateway } = testEnv; const user = users[0]; const amount = parseEther('1'); const fakeABI = ['function wantToCallFallback()']; @@ -260,7 +280,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Should revert if fallback functions is called', async () => { - const {users, wethGateway} = testEnv; + const { users, wethGateway } = testEnv; const user = users[0]; const fakeABI = ['function wantToCallFallback()']; @@ -278,7 +298,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Getters should retrieve correct state', async () => { - const {aWETH, weth, pool, wethGateway} = testEnv; + const { aWETH, weth, pool, wethGateway } = testEnv; const WETHAddress = await wethGateway.getWETHAddress(); const aWETHAddress = await wethGateway.getAWETHAddress(); @@ -290,7 +310,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Owner can do emergency token recovery', async () => { - const {users, dai, wethGateway, deployer} = testEnv; + const { users, dai, wethGateway, deployer } = testEnv; const user = users[0]; const amount = parseEther('1'); @@ -316,7 +336,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Owner can do emergency native ETH recovery', async () => { - const {users, wethGateway, deployer} = testEnv; + const { users, wethGateway, deployer } = testEnv; const user = users[0]; const amount = parseEther('1'); const userBalancePriorCall = await user.signer.getBalance(); @@ -327,13 +347,13 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Selfdestruct the mock, pointing to WETHGateway address const callTx = await selfdestructContract .connect(user.signer) - .destroyAndTransfer(wethGateway.address, {value: amount}); - const {gasUsed} = await waitForTx(callTx); + .destroyAndTransfer(wethGateway.address, { value: amount }); + const { gasUsed } = await waitForTx(callTx); const gasFees = gasUsed.mul(callTx.gasPrice); const userBalanceAfterCall = await user.signer.getBalance(); expect(userBalanceAfterCall).to.be.eq(userBalancePriorCall.sub(amount).sub(gasFees), ''); - 'User should have lost the funds'; + ('User should have lost the funds'); // Recover the funds from the contract and sends back to the user await wethGateway.connect(deployer.signer).emergencyEtherTransfer(user.address, amount); From 073b30d8c9373a34afd4e0e286180b2a0918d6a0 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 20 Jan 2021 21:44:19 -0500 Subject: [PATCH 026/219] Added assets & fixed test --- helpers/types.ts | 19 +++++ markets/uniswap/commons.ts | 2 +- markets/uniswap/reservesConfigs.ts | 132 ++++++++++++++--------------- tasks/dev/4_oracles.ts | 1 - test/__setup.spec.ts | 21 ++++- 5 files changed, 105 insertions(+), 70 deletions(-) diff --git a/helpers/types.ts b/helpers/types.ts index 0a2b7194..79511ee3 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -301,6 +301,25 @@ export enum TokenContractId { YFI = 'YFI', UNI = 'UNI', ENJ = 'ENJ', + UniWETH = 'UniWETH', + UniWBTC = 'UniWBTC', + UniDAI = 'UniDAI', + UniUSDC = 'UniUSDC', + UniUSDT = 'UniUSDT', + UniDAIWETH = 'UniDAIWETH', + UniWBTCWETH = 'UniWBTCWETH', + UniAAVEWETH = 'UniAAVEWETH', + UniBATWETH = 'UniBATWETH', + UniUSDCDAI = 'UniUSDCDAI', + UniCRVWETH = 'UniCRVWETH', + UniLINKWETH = 'UniLINKWETH', + UniMKRWETH = 'UniMKRWETH', + UniRENWETH = 'UniRENWETH', + UniSNXWETH = 'UniSNXWETH', + UniUNIWETH = 'UniUNIWETH', + UniUSDCWETH = 'UniUSDCWETH', + UniWBTCUSDC = 'UniWBTCUSDC', + UniYFIWETH = 'UniYFIWETH', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { diff --git a/markets/uniswap/commons.ts b/markets/uniswap/commons.ts index 0aa7b4bc..b037f859 100644 --- a/markets/uniswap/commons.ts +++ b/markets/uniswap/commons.ts @@ -241,7 +241,7 @@ export const CommonsConfig: ICommonConfiguration = { UniWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', UniUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', UniDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', - UniDAIWETH: ZERO_ADDRESS, + UniDAIWETH: '0xf4071801C4421Db7e63DaC15B9432e50C44a7F42', UniWBTCWETH: ZERO_ADDRESS, UniAAVEWETH: ZERO_ADDRESS, UniBATWETH: ZERO_ADDRESS, diff --git a/markets/uniswap/reservesConfigs.ts b/markets/uniswap/reservesConfigs.ts index aed62b2d..84ab8317 100644 --- a/markets/uniswap/reservesConfigs.ts +++ b/markets/uniswap/reservesConfigs.ts @@ -13,7 +13,7 @@ export const strategyWETH: IReserveParams = { liquidationThreshold: '8250', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -21,7 +21,7 @@ export const strategyWETH: IReserveParams = { export const strategyWBTC: IReserveParams = { optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', + 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(), @@ -30,7 +30,7 @@ export const strategyWBTC: IReserveParams = { liquidationThreshold: '7500', liquidationBonus: '11000', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '8', aTokenImpl: eContractid.AToken, reserveFactor: '2000' @@ -47,51 +47,51 @@ export const strategyDAI: IReserveParams = { liquidationThreshold: '8000', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000' }; export const strategyUSDC: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.9).multipliedBy(oneRay).toFixed(), + 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.60).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(), stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(), stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(), baseLTVAsCollateral: '8000', liquidationThreshold: '8500', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '6', aTokenImpl: eContractid.AToken, reserveFactor: '1000' }; export const strategyUSDT: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.9).multipliedBy(oneRay).toFixed(), + 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.60).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(), stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(), stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(), baseLTVAsCollateral: '8000', liquidationThreshold: '8500', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '6', aTokenImpl: eContractid.AToken, reserveFactor: '1000' }; export const strategyDAIWETH: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '6000', @@ -105,10 +105,10 @@ export const strategyDAIWETH: IReserveParams = { }; export const strategyWBTCWETH: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '6000', @@ -122,10 +122,10 @@ export const strategyWBTCWETH: IReserveParams = { }; export const strategyAAVEWETH: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '6000', @@ -139,10 +139,10 @@ export const strategyAAVEWETH: IReserveParams = { }; export const strategyBATWETH: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '6000', @@ -156,10 +156,10 @@ export const strategyBATWETH: IReserveParams = { }; export const strategyUSDCDAI: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '6000', @@ -173,10 +173,10 @@ export const strategyUSDCDAI: IReserveParams = { }; export const strategyCRVWETH: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '5000', @@ -190,10 +190,10 @@ export const strategyCRVWETH: IReserveParams = { }; export const strategyLINKWETH: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '6000', @@ -207,10 +207,10 @@ export const strategyLINKWETH: IReserveParams = { }; export const strategyMKRWETH: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '6000', @@ -224,10 +224,10 @@ export const strategyMKRWETH: IReserveParams = { }; export const strategyRENWETH: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '6000', @@ -241,10 +241,10 @@ export const strategyRENWETH: IReserveParams = { }; export const strategySNXWETH: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '4000', @@ -258,10 +258,10 @@ export const strategySNXWETH: IReserveParams = { }; export const strategyUNIWETH: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '6000', @@ -275,10 +275,10 @@ export const strategyUNIWETH: IReserveParams = { }; export const strategyUSDCWETH: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '6000', @@ -292,10 +292,10 @@ export const strategyUSDCWETH: IReserveParams = { }; export const strategyWBTCUSDC: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '6000', @@ -309,10 +309,10 @@ export const strategyWBTCUSDC: IReserveParams = { }; export const strategyYFIWETH: IReserveParams = { - optimalUtilizationRate: new BigNumber(0.6).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), stableRateSlope1: '0', stableRateSlope2: '0', baseLTVAsCollateral: '5000', diff --git a/tasks/dev/4_oracles.ts b/tasks/dev/4_oracles.ts index 97f14c8a..82380b01 100644 --- a/tasks/dev/4_oracles.ts +++ b/tasks/dev/4_oracles.ts @@ -4,7 +4,6 @@ import { deployAaveOracle, deployLendingRateOracle, } from '../../helpers/contracts-deployments'; - import { setInitialAssetPricesInOracle, deployAllMockAggregators, diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index 7d2bb638..a8aa9854 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -159,8 +159,25 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { REN: mockTokens.REN.address, UNI: mockTokens.UNI.address, ENJ: mockTokens.ENJ.address, - WETHDAI: mockTokens.WETHDAI.address, - WETHWBTC: mockTokens.WETHWBTC.address, + UniDAI: mockTokens.UniDAI.address, + UniUSDC: mockTokens.UniUSDC.address, + UniUSDT: mockTokens.UniUSDT.address, + UniWBTC: mockTokens.UniWBTC.address, + UniWETH: mockTokens.UniWETH.address, + UniDAIWETH: mockTokens.UniDAIWETH.address, + UniWBTCWETH: mockTokens.UniWBTCWETH.address, + UniAAVEWETH: mockTokens.UniAAVEWETH.address, + UniBATWETH: mockTokens.UniBATWETH.address, + UniUSDCDAI: mockTokens.UniUSDCDAI.address, + UniCRVWETH: mockTokens.UniCRVWETH.address, + UniLINKWETH: mockTokens.UniLINKWETH.address, + UniMKRWETH: mockTokens.UniMKRWETH.address, + UniRENWETH: mockTokens.UniRENWETH.address, + UniSNXWETH: mockTokens.UniSNXWETH.address, + UniUNIWETH: mockTokens.UniUNIWETH.address, + UniUSDCWETH: mockTokens.UniUSDCWETH.address, + UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, + UniYFIWETH: mockTokens.UniYFIWETH.address, USD: USD_ADDRESS, }, fallbackOracle From 6cebf50f1114e39daa302e372c92bea3307903df Mon Sep 17 00:00:00 2001 From: andyk Date: Thu, 21 Jan 2021 17:44:48 +0300 Subject: [PATCH 027/219] add special quotation flow --- contracts/adapters/BaseUniswapAdapter.sol | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/contracts/adapters/BaseUniswapAdapter.sol b/contracts/adapters/BaseUniswapAdapter.sol index b04bc8a1..cb277f2c 100644 --- a/contracts/adapters/BaseUniswapAdapter.sol +++ b/contracts/adapters/BaseUniswapAdapter.sol @@ -346,6 +346,18 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt // Subtract flash loan fee uint256 finalAmountIn = amountIn.sub(amountIn.mul(FLASHLOAN_PREMIUM_TOTAL).div(10000)); + if (reserveIn == reserveOut) { + uint256 reserveDecimals = _getDecimals(reserveIn); + return + AmountCalc( + finalAmountIn, + finalAmountIn.mul(10**18).div(amountIn), + _calcUsdValue(reserveIn, amountIn, reserveDecimals), + _calcUsdValue(reserveIn, finalAmountIn, reserveDecimals), + [reserveIn] + ); + } + address[] memory simplePath = new address[](2); simplePath[0] = reserveIn; simplePath[1] = reserveOut; @@ -420,6 +432,20 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt address reserveOut, uint256 amountOut ) internal view returns (AmountCalc memory) { + if (reserveIn == reserveOut) { + // Add flash loan fee + uint256 amountIn = amountOut.add(amountOut.mul(FLASHLOAN_PREMIUM_TOTAL).div(10000)); + uint256 reserveDecimals = _getDecimals(reserveIn); + return + AmountCalc( + amountIn, + amountOut.mul(10**18).div(amountIn), + _calcUsdValue(reserveIn, amountIn, reserveDecimals), + _calcUsdValue(reserveIn, amountOut, reserveDecimals), + [reserveIn] + ); + } + (uint256[] memory amounts, address[] memory path) = _getAmountsInAndPath(reserveIn, reserveOut, amountOut); From f05550fc04b17eeda8d4511b99ec1eb25f0d3e9f Mon Sep 17 00:00:00 2001 From: David Racero Date: Thu, 21 Jan 2021 20:21:56 +0100 Subject: [PATCH 028/219] Fixed master tests --- test/helpers/utils/calculations.ts | 37 ++++++++++-- test/uniswapAdapters.repay.spec.ts | 92 ++++++++++++++++++++---------- 2 files changed, 93 insertions(+), 36 deletions(-) diff --git a/test/helpers/utils/calculations.ts b/test/helpers/utils/calculations.ts index 752207e6..a4db008f 100644 --- a/test/helpers/utils/calculations.ts +++ b/test/helpers/utils/calculations.ts @@ -996,7 +996,7 @@ export const calcExpectedReserveDataAfterStableRateRebalance = ( //removing the stable liquidity at the old rate - const avgRateBefore = calcExpectedAverageStableBorrowRate( + const avgRateBefore = calcExpectedAverageStableBorrowRateRebalance( reserveDataBeforeAction.averageStableBorrowRate, expectedReserveData.totalStableDebt, userStableDebt.negated(), @@ -1004,7 +1004,7 @@ export const calcExpectedReserveDataAfterStableRateRebalance = ( ); // adding it again at the new rate - expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( + expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRateRebalance( avgRateBefore, expectedReserveData.totalStableDebt.minus(userStableDebt), userStableDebt, @@ -1044,6 +1044,8 @@ export const calcExpectedUserDataAfterStableRateRebalance = ( ): UserReserveData => { const expectedUserData = { ...userDataBeforeAction }; + expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; + expectedUserData.principalVariableDebt = calcExpectedVariableDebtTokenBalance( reserveDataBeforeAction, userDataBeforeAction, @@ -1056,12 +1058,18 @@ export const calcExpectedUserDataAfterStableRateRebalance = ( txTimestamp ); + expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + expectedUserData.stableRateLastUpdated = txTimestamp; expectedUserData.principalVariableDebt = userDataBeforeAction.principalVariableDebt; - expectedUserData.stableBorrowRate = reserveDataBeforeAction.stableBorrowRate; - + // Stable rate after burn + expectedUserData.stableBorrowRate = expectedDataAfterAction.averageStableBorrowRate; expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; expectedUserData.currentATokenBalance = calcExpectedATokenBalance( @@ -1104,7 +1112,7 @@ const calcExpectedAverageStableBorrowRate = ( ) => { const weightedTotalBorrows = avgStableRateBefore.multipliedBy(totalStableDebtBefore); const weightedAmountBorrowed = rate.multipliedBy(amountChanged); - const totalBorrowedStable = totalStableDebtBefore.plus(new BigNumber(amountChanged)); + const totalBorrowedStable = totalStableDebtBefore.plus(amountChanged); if (totalBorrowedStable.eq(0)) return new BigNumber('0'); @@ -1114,6 +1122,24 @@ const calcExpectedAverageStableBorrowRate = ( .decimalPlaces(0, BigNumber.ROUND_DOWN); }; +const calcExpectedAverageStableBorrowRateRebalance = ( + avgStableRateBefore: BigNumber, + totalStableDebtBefore: BigNumber, + amountChanged: BigNumber, + rate: BigNumber +) => { + const weightedTotalBorrows = avgStableRateBefore.rayMul(totalStableDebtBefore); + const weightedAmountBorrowed = rate.rayMul(amountChanged.wadToRay()); + const totalBorrowedStable = totalStableDebtBefore.plus(amountChanged.wadToRay()); + + if (totalBorrowedStable.eq(0)) return new BigNumber('0'); + + return weightedTotalBorrows + .plus(weightedAmountBorrowed) + .rayDiv(totalBorrowedStable) + .decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + export const calcExpectedVariableDebtTokenBalance = ( reserveData: ReserveData, userData: UserReserveData, @@ -1211,7 +1237,6 @@ export const calcExpectedInterestRates = ( ): BigNumber[] => { const { reservesParams } = configuration; - const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol); const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[ reserveIndex diff --git a/test/uniswapAdapters.repay.spec.ts b/test/uniswapAdapters.repay.spec.ts index 27f91e02..c271917e 100644 --- a/test/uniswapAdapters.repay.spec.ts +++ b/test/uniswapAdapters.repay.spec.ts @@ -17,6 +17,7 @@ import { eContractid } from '../helpers/types'; import { StableDebtToken } from '../types/StableDebtToken'; import { BUIDLEREVM_CHAINID } from '../helpers/buidler-constants'; import { MAX_UINT_AMOUNT } from '../helpers/constants'; +import { VariableDebtToken } from '../types'; const { parseEther } = ethers.utils; const { expect } = require('chai'); @@ -797,7 +798,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); }); - it('should correctly repay debt using the same asset as collateral', async () => { + it('should correctly repay debt via flash loan using the same asset as collateral', async () => { const { users, pool, aDai, dai, uniswapRepayAdapter, helpersContract } = testEnv; const user = users[0].signer; const userAddress = users[0].address; @@ -813,16 +814,18 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { // Open user Debt await pool.connect(user).borrow(dai.address, debtAmount, 2, 0, userAddress); - const daiStableDebtTokenAddress = ( + const daiVariableDebtTokenAddress = ( await helpersContract.getReserveTokensAddresses(dai.address) - ).stableDebtTokenAddress; + ).variableDebtTokenAddress; - const daiStableDebtContract = await getContract( - eContractid.StableDebtToken, - daiStableDebtTokenAddress + const daiVariableDebtContract = await getContract( + eContractid.VariableDebtToken, + daiVariableDebtTokenAddress ); - const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( + userAddress + ); const flashLoanDebt = new BigNumber(amountCollateralToSwap.toString()) .multipliedBy(1.0009) @@ -835,7 +838,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { const params = buildRepayAdapterParams( dai.address, amountCollateralToSwap, - 1, + 2, 0, 0, 0, @@ -857,18 +860,30 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { ); const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); + const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); const userADaiBalance = await aDai.balanceOf(userAddress); const adapterADaiBalance = await aDai.balanceOf(uniswapRepayAdapter.address); const userDaiBalance = await dai.balanceOf(userAddress); - expect(adapterADaiBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(userDaiStableDebtAmountBefore).to.be.gte(debtAmount); - expect(userDaiStableDebtAmount).to.be.lt(debtAmount); - expect(userADaiBalance).to.be.lt(userADaiBalanceBefore); - expect(userADaiBalance).to.be.gte(userADaiBalanceBefore.sub(flashLoanDebt)); - expect(userDaiBalance).to.be.eq(userDaiBalanceBefore); + expect(adapterADaiBalance).to.be.eq(Zero, 'adapter aDAI balance should be zero'); + expect(adapterDaiBalance).to.be.eq(Zero, 'adapter DAI balance should be zero'); + expect(userDaiVariableDebtAmountBefore).to.be.gte( + debtAmount, + ' user DAI variable debt before should be gte debtAmount' + ); + expect(userDaiVariableDebtAmount).to.be.lt( + debtAmount, + 'user dai variable debt amount should be lt debt amount' + ); + expect(userADaiBalance).to.be.lt( + userADaiBalanceBefore, + 'user aDAI balance should be lt aDAI prior balance' + ); + expect(userADaiBalance).to.be.gte( + userADaiBalanceBefore.sub(flashLoanDebt), + 'user aDAI balance should be gte aDAI prior balance sub flash loan debt' + ); + expect(userDaiBalance).to.be.eq(userDaiBalanceBefore, 'user dai balance eq prior balance'); }); }); @@ -1387,16 +1402,18 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { // Open user Debt await pool.connect(user).borrow(dai.address, debtAmount, 2, 0, userAddress); - const daiStableDebtTokenAddress = ( + const daiVariableDebtTokenAddress = ( await helpersContract.getReserveTokensAddresses(dai.address) - ).stableDebtTokenAddress; + ).variableDebtTokenAddress; - const daiStableDebtContract = await getContract( + const daiVariableDebtContract = await getContract( eContractid.StableDebtToken, - daiStableDebtTokenAddress + daiVariableDebtTokenAddress ); - const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( + userAddress + ); await aDai.connect(user).approve(uniswapRepayAdapter.address, amountCollateralToSwap); const userADaiBalanceBefore = await aDai.balanceOf(userAddress); @@ -1407,7 +1424,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { dai.address, amountCollateralToSwap, amountCollateralToSwap, - 1, + 2, { amount: 0, deadline: 0, @@ -1419,18 +1436,33 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { ); const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); + const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); const userADaiBalance = await aDai.balanceOf(userAddress); const adapterADaiBalance = await aDai.balanceOf(uniswapRepayAdapter.address); const userDaiBalance = await dai.balanceOf(userAddress); - expect(adapterADaiBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(userDaiStableDebtAmountBefore).to.be.gte(debtAmount); - expect(userDaiStableDebtAmount).to.be.lt(debtAmount); - expect(userADaiBalance).to.be.lt(userADaiBalanceBefore); - expect(userADaiBalance).to.be.gte(userADaiBalanceBefore.sub(amountCollateralToSwap)); - expect(userDaiBalance).to.be.eq(userDaiBalanceBefore); + expect(adapterADaiBalance).to.be.eq(Zero, 'adapter aADAI should be zero'); + expect(adapterDaiBalance).to.be.eq(Zero, 'adapter DAI should be zero'); + expect(userDaiVariableDebtAmountBefore).to.be.gte( + debtAmount, + 'user dai variable debt before should be gte debtAmount' + ); + expect(userDaiVariableDebtAmount).to.be.lt( + debtAmount, + 'current user dai variable debt amount should be less than debtAmount' + ); + expect(userADaiBalance).to.be.lt( + userADaiBalanceBefore, + 'current user aDAI balance should be less than prior balance' + ); + expect(userADaiBalance).to.be.gte( + userADaiBalanceBefore.sub(amountCollateralToSwap), + 'current user aDAI balance should be gte user balance sub swapped collateral' + ); + expect(userDaiBalance).to.be.eq( + userDaiBalanceBefore, + 'user DAI balance should remain equal' + ); }); }); }); From 55f14c1af932d31465d8e0561195ccf439a0f243 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 22 Jan 2021 09:59:47 +0000 Subject: [PATCH 029/219] Use diff balances instead of liquidation logic for flash liquidations --- .../adapters/FlashLiquidationAdapter.sol | 144 +++--------------- test/uniswapAdapters.flashLiquidation.spec.ts | 4 +- 2 files changed, 27 insertions(+), 121 deletions(-) diff --git a/contracts/adapters/FlashLiquidationAdapter.sol b/contracts/adapters/FlashLiquidationAdapter.sol index 8c4703ce..459c038e 100644 --- a/contracts/adapters/FlashLiquidationAdapter.sol +++ b/contracts/adapters/FlashLiquidationAdapter.sol @@ -30,20 +30,11 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { } struct LiquidationCallLocalVars { - uint256 userCollateralBalance; - uint256 userStableDebt; - uint256 userVariableDebt; - uint256 maxLiquidatableDebt; - uint256 actualDebtToLiquidate; - uint256 maxAmountCollateralToLiquidate; - uint256 maxCollateralToLiquidate; - uint256 debtAmountNeeded; - uint256 collateralPrice; - uint256 debtAssetPrice; - uint256 liquidationBonus; - uint256 collateralDecimals; - uint256 debtAssetDecimals; - IAToken collateralAtoken; + uint256 initCollateralBalance; + uint256 diffCollateralBalance; + uint256 flashLoanDebt; + uint256 soldAmount; + uint256 remainingTokens; } constructor( @@ -115,63 +106,38 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { uint256 premium, address initiator ) internal { - DataTypes.ReserveData memory collateralReserve = LENDING_POOL.getReserveData(collateralAsset); - DataTypes.ReserveData memory debtReserve = LENDING_POOL.getReserveData(debtAsset); LiquidationCallLocalVars memory vars; + vars.initCollateralBalance = IERC20(collateralAsset).balanceOf(address(this)); + vars.flashLoanDebt = coverAmount.add(premium); - (vars.userStableDebt, vars.userVariableDebt) = Helpers.getUserCurrentDebtMemory( - user, - debtReserve - ); - vars.collateralAtoken = IAToken(collateralReserve.aTokenAddress); - vars.maxLiquidatableDebt = vars.userStableDebt.add(vars.userVariableDebt).percentMul( - LIQUIDATION_CLOSE_FACTOR_PERCENT - ); - - vars.userCollateralBalance = vars.collateralAtoken.balanceOf(user); - vars.actualDebtToLiquidate = debtToCover > vars.maxLiquidatableDebt - ? vars.maxLiquidatableDebt - : debtToCover; - - ( - vars.maxCollateralToLiquidate, - vars.debtAmountNeeded - ) = _calculateAvailableCollateralToLiquidate( - collateralReserve, - debtReserve, - collateralAsset, - debtAsset, - vars.actualDebtToLiquidate, - vars.userCollateralBalance - ); - - require(coverAmount >= vars.debtAmountNeeded, 'FLASH_COVER_NOT_ENOUGH'); - - uint256 flashLoanDebt = coverAmount.add(premium); - + // Approve LendingPool to use debt token for liquidation IERC20(debtAsset).approve(address(LENDING_POOL), debtToCover); // Liquidate the user position and release the underlying collateral LENDING_POOL.liquidationCall(collateralAsset, debtAsset, user, debtToCover, false); + // Discover the liquidated tokens + vars.diffCollateralBalance = IERC20(collateralAsset).balanceOf(address(this)).sub( + vars.initCollateralBalance + ); + // Swap released collateral into the debt asset, to repay the flash loan - uint256 soldAmount = - _swapTokensForExactTokens( - collateralAsset, - debtAsset, - vars.maxCollateralToLiquidate, - flashLoanDebt, - useEthPath - ); + vars.soldAmount = _swapTokensForExactTokens( + collateralAsset, + debtAsset, + vars.diffCollateralBalance, + vars.flashLoanDebt, + useEthPath + ); - // Repay flash loan - IERC20(debtAsset).approve(address(LENDING_POOL), flashLoanDebt); + // Allow repay of flash loan + IERC20(debtAsset).approve(address(LENDING_POOL), vars.flashLoanDebt); - uint256 remainingTokens = vars.maxCollateralToLiquidate.sub(soldAmount); + vars.remainingTokens = vars.diffCollateralBalance.sub(vars.soldAmount); // Transfer remaining tokens to initiator - if (remainingTokens > 0) { - IERC20(collateralAsset).transfer(initiator, remainingTokens); + if (vars.remainingTokens > 0) { + IERC20(collateralAsset).transfer(initiator, vars.remainingTokens); } } @@ -196,64 +162,4 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { return LiquidationParams(collateralAsset, debtAsset, user, debtToCover, useEthPath); } - - /** - * @dev Calculates how much of a specific collateral can be liquidated, given - * a certain amount of debt asset. - * - This function needs to be called after all the checks to validate the liquidation have been performed, - * otherwise it might fail. - * @param collateralReserve The data of the collateral reserve - * @param debtReserve The data of the debt reserve - * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation - * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation - * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover - * @param userCollateralBalance The collateral balance for the specific `collateralAsset` of the user being liquidated - * @return collateralAmount: The maximum amount that is possible to liquidate given all the liquidation constraints - * (user balance, close factor) - * debtAmountNeeded: The amount to repay with the liquidation - **/ - function _calculateAvailableCollateralToLiquidate( - DataTypes.ReserveData memory collateralReserve, - DataTypes.ReserveData memory debtReserve, - address collateralAsset, - address debtAsset, - uint256 debtToCover, - uint256 userCollateralBalance - ) internal view returns (uint256, uint256) { - uint256 collateralAmount = 0; - uint256 debtAmountNeeded = 0; - - LiquidationCallLocalVars memory vars; - - vars.collateralPrice = ORACLE.getAssetPrice(collateralAsset); - vars.debtAssetPrice = ORACLE.getAssetPrice(debtAsset); - - (, , vars.liquidationBonus, vars.collateralDecimals, ) = collateralReserve - .configuration - .getParamsMemory(); - (, , , vars.debtAssetDecimals, ) = debtReserve.configuration.getParamsMemory(); - - // This is the maximum possible amount of the selected collateral that can be liquidated, given the - // max amount of liquidatable debt - vars.maxAmountCollateralToLiquidate = vars - .debtAssetPrice - .mul(debtToCover) - .mul(10**vars.collateralDecimals) - .percentMul(vars.liquidationBonus) - .div(vars.collateralPrice.mul(10**vars.debtAssetDecimals)); - - if (vars.maxAmountCollateralToLiquidate > userCollateralBalance) { - collateralAmount = userCollateralBalance; - debtAmountNeeded = vars - .collateralPrice - .mul(collateralAmount) - .mul(10**vars.debtAssetDecimals) - .div(vars.debtAssetPrice.mul(10**vars.collateralDecimals)) - .percentDiv(vars.liquidationBonus); - } else { - collateralAmount = vars.maxAmountCollateralToLiquidate; - debtAmountNeeded = debtToCover; - } - return (collateralAmount, debtAmountNeeded); - } } diff --git a/test/uniswapAdapters.flashLiquidation.spec.ts b/test/uniswapAdapters.flashLiquidation.spec.ts index ff2284e3..ab5a0bd1 100644 --- a/test/uniswapAdapters.flashLiquidation.spec.ts +++ b/test/uniswapAdapters.flashLiquidation.spec.ts @@ -18,13 +18,13 @@ const { expect } = require('chai'); makeSuite('Uniswap adapters', (testEnv: TestEnv) => { let mockUniswapRouter: MockUniswapV2Router02; let evmSnapshotId: string; + const { INVALID_HF, LP_LIQUIDATION_CALL_FAILED } = ProtocolErrors; before(async () => { mockUniswapRouter = await getMockUniswapRouter(); }); const depositAndHFBelowOne = async () => { - const { INVALID_HF } = ProtocolErrors; const { dai, weth, users, pool, oracle } = testEnv; const depositor = users[0]; const borrower = users[1]; @@ -643,7 +643,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { params, 0 ) - ).to.be.revertedWith('FLASH_COVER_NOT_ENOUGH'); + ).to.be.revertedWith(LP_LIQUIDATION_CALL_FAILED); }); it('Revert if requested multiple assets', async () => { From d6059938bbf855d504097a24f448aa5356ea83c1 Mon Sep 17 00:00:00 2001 From: eboado Date: Mon, 25 Jan 2021 09:29:07 +0100 Subject: [PATCH 030/219] - Fixed array init on BaseUniswapAdapter --- contracts/adapters/BaseUniswapAdapter.sol | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/contracts/adapters/BaseUniswapAdapter.sol b/contracts/adapters/BaseUniswapAdapter.sol index cb277f2c..1a962473 100644 --- a/contracts/adapters/BaseUniswapAdapter.sol +++ b/contracts/adapters/BaseUniswapAdapter.sol @@ -348,13 +348,16 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt if (reserveIn == reserveOut) { uint256 reserveDecimals = _getDecimals(reserveIn); + address[] memory path = new address[](1); + path[0] = reserveIn; + return AmountCalc( finalAmountIn, finalAmountIn.mul(10**18).div(amountIn), _calcUsdValue(reserveIn, amountIn, reserveDecimals), _calcUsdValue(reserveIn, finalAmountIn, reserveDecimals), - [reserveIn] + path ); } @@ -436,13 +439,16 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt // Add flash loan fee uint256 amountIn = amountOut.add(amountOut.mul(FLASHLOAN_PREMIUM_TOTAL).div(10000)); uint256 reserveDecimals = _getDecimals(reserveIn); + address[] memory path = new address[](1); + path[0] = reserveIn; + return AmountCalc( amountIn, amountOut.mul(10**18).div(amountIn), _calcUsdValue(reserveIn, amountIn, reserveDecimals), _calcUsdValue(reserveIn, amountOut, reserveDecimals), - [reserveIn] + path ); } From 56ba85e9463e2c7716684bfa5c86a03ade9b08d8 Mon Sep 17 00:00:00 2001 From: David Racero Date: Tue, 26 Jan 2021 12:56:36 +0100 Subject: [PATCH 031/219] Add publish to Gitlab CI --- .gitlab-ci.yml | 26 ++++++++++++++++++++++++++ package.json | 48 +++++++++++++++++++++--------------------------- 2 files changed, 47 insertions(+), 27 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b012440d..4274147d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,10 @@ stages: - checks + - prepare + - publish + +variables: + IMAGE: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA} test: stage: checks @@ -40,3 +45,24 @@ certora-test: - certoraRun specs/harness/StableDebtTokenHarness.sol:StableDebtTokenHarness --solc_args "['--optimize']" --verify StableDebtTokenHarness:specs/StableDebtToken.spec --settings -assumeUnwindCond,-b=4 --cache StableDebtToken --cloud - certoraRun specs/harness/UserConfigurationHarness.sol --verify UserConfigurationHarness:specs/UserConfiguration.spec --solc_args "['--optimize']" --settings -useBitVectorTheory --cache UserConfiguration --cloud - certoraRun contracts/protocol/tokenization/VariableDebtToken.sol:VariableDebtToken specs/harness/LendingPoolHarnessForVariableDebtToken.sol --solc_args "['--optimize']" --link VariableDebtToken:POOL=LendingPoolHarnessForVariableDebtToken --verify VariableDebtToken:specs/VariableDebtToken.spec --settings -assumeUnwindCond,-useNonLinearArithmetic,-b=4 --cache VariableDebtToken --cloud + +prepare: + stage: prepare + tags: + - docker-builder + script: + - docker build -t ${IMAGE} . + - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY + - docker push ${IMAGE} + only: + - master + +publish: + extends: .image_step + stage: publish + script: + - npm ci + - echo //registry.npmjs.org/:_authToken=${NPM_V2_PACKAGES_TOKEN} > .npmrc + - npm run compile + - ${VERSION} + - npm publish --access public diff --git a/package.json b/package.json index 4fefea1b..ea016bca 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,11 @@ { - "name": "protocol-v2", + "name": "@aave/protocol-v2", "version": "1.0.0", "description": "Aave Protocol V2 smart contracts", + "files": [ + "contracts", + "artifacts" + ], "scripts": { "run-env": "npm i && tail -f /dev/null", "hardhat": "hardhat", @@ -62,7 +66,8 @@ "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", "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" + "external:deploy-assets-main": "npm run compile && hardhat --network main external:deploy-new-asset --symbol ${SYMBOL} --verify", + "prepublishOnly": "npm run compile" }, "devDependencies": { "@nomiclabs/buidler": "^1.4.7", @@ -118,33 +123,22 @@ }, "author": "Aave", "contributors": [ - { - "name": "Emilio Frangella", - "email": "emilio@aave.com" - }, - { - "name": "Ernesto Boado", - "email": "ernesto@aave.com" - }, - { - "name": "Andrey Kozlov", - "email": "andrey@aave.com" - }, - { - "name": "David Racero", - "email": "david.k@aave.com" - }, - { - "name": "Pol Sendra", - "email": "pol@aave.com" - }, - { - "name": "David Truong", - "email": "david@aave.com" - } + "Ernesto Boado ", + "Emilio Frangella ", + "Andrey Kozlov ", + "David Racero ", + "Pol Sendra ", + "David Truong " ], "license": "AGPLv3", "dependencies": { "tmp-promise": "^3.0.2" - } + }, + "keywords": [ + "aave", + "protocol", + "protocol-v2", + "ethereum", + "solidity" + ] } From 9cd6175f111e2d38f34cd4ac35c659a041323551 Mon Sep 17 00:00:00 2001 From: David Racero Date: Tue, 26 Jan 2021 12:58:39 +0100 Subject: [PATCH 032/219] Fix gitlab ci --- .gitlab-ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4274147d..25a2d513 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -58,7 +58,9 @@ prepare: - master publish: - extends: .image_step + image: ${IMAGE} + tags: + - docker stage: publish script: - npm ci From 422d843815332c954983fc735bb5fc5ed627b8d1 Mon Sep 17 00:00:00 2001 From: David Racero Date: Tue, 26 Jan 2021 13:01:37 +0100 Subject: [PATCH 033/219] Run CI to test publish image prepare --- .gitlab-ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 25a2d513..aef1554d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -56,6 +56,7 @@ prepare: - docker push ${IMAGE} only: - master + - merge_requests publish: image: ${IMAGE} @@ -68,3 +69,6 @@ publish: - npm run compile - ${VERSION} - npm publish --access public + only: + - master + - merge_requests From 5434b279d1bcccde91189598400d0469349c7ab3 Mon Sep 17 00:00:00 2001 From: David Racero Date: Tue, 26 Jan 2021 13:03:06 +0100 Subject: [PATCH 034/219] Fix detached missing tests --- .gitlab-ci.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index aef1554d..1e0afada 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,6 +17,9 @@ test: after_script: - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down + only: + - master + - merge_requests deploy-mainnet-fork: tags: @@ -29,6 +32,9 @@ deploy-mainnet-fork: after_script: - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down + only: + - master + - merge_requests certora-test: stage: checks @@ -45,6 +51,9 @@ certora-test: - certoraRun specs/harness/StableDebtTokenHarness.sol:StableDebtTokenHarness --solc_args "['--optimize']" --verify StableDebtTokenHarness:specs/StableDebtToken.spec --settings -assumeUnwindCond,-b=4 --cache StableDebtToken --cloud - certoraRun specs/harness/UserConfigurationHarness.sol --verify UserConfigurationHarness:specs/UserConfiguration.spec --solc_args "['--optimize']" --settings -useBitVectorTheory --cache UserConfiguration --cloud - certoraRun contracts/protocol/tokenization/VariableDebtToken.sol:VariableDebtToken specs/harness/LendingPoolHarnessForVariableDebtToken.sol --solc_args "['--optimize']" --link VariableDebtToken:POOL=LendingPoolHarnessForVariableDebtToken --verify VariableDebtToken:specs/VariableDebtToken.spec --settings -assumeUnwindCond,-useNonLinearArithmetic,-b=4 --cache VariableDebtToken --cloud + only: + - master + - merge_requests prepare: stage: prepare From 2f4219d6430c01d07528d00b0a585c2329fd5aad Mon Sep 17 00:00:00 2001 From: David Racero Date: Tue, 26 Jan 2021 13:20:32 +0100 Subject: [PATCH 035/219] Detach mode to test prepare and publish step --- .gitlab-ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1e0afada..b743cdbe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -51,9 +51,6 @@ certora-test: - certoraRun specs/harness/StableDebtTokenHarness.sol:StableDebtTokenHarness --solc_args "['--optimize']" --verify StableDebtTokenHarness:specs/StableDebtToken.spec --settings -assumeUnwindCond,-b=4 --cache StableDebtToken --cloud - certoraRun specs/harness/UserConfigurationHarness.sol --verify UserConfigurationHarness:specs/UserConfiguration.spec --solc_args "['--optimize']" --settings -useBitVectorTheory --cache UserConfiguration --cloud - certoraRun contracts/protocol/tokenization/VariableDebtToken.sol:VariableDebtToken specs/harness/LendingPoolHarnessForVariableDebtToken.sol --solc_args "['--optimize']" --link VariableDebtToken:POOL=LendingPoolHarnessForVariableDebtToken --verify VariableDebtToken:specs/VariableDebtToken.spec --settings -assumeUnwindCond,-useNonLinearArithmetic,-b=4 --cache VariableDebtToken --cloud - only: - - master - - merge_requests prepare: stage: prepare From e84ab7cf0355eb2a146f10ab6750fab73040095f Mon Sep 17 00:00:00 2001 From: David Racero Date: Tue, 26 Jan 2021 13:34:39 +0100 Subject: [PATCH 036/219] Allow detached to skip tests for testing publish --- .gitlab-ci.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b743cdbe..aef1554d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,9 +17,6 @@ test: after_script: - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down - only: - - master - - merge_requests deploy-mainnet-fork: tags: @@ -32,9 +29,6 @@ deploy-mainnet-fork: after_script: - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down - only: - - master - - merge_requests certora-test: stage: checks From 9169e0db62dbfe8122de848ae0c295ac7f683af9 Mon Sep 17 00:00:00 2001 From: David Racero Date: Tue, 26 Jan 2021 13:46:48 +0100 Subject: [PATCH 037/219] Add notes about how to use NPM package to import contract or artifacts --- README.md | 31 +++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aba2356e..739ef23c 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,37 @@ A more detailed and technical description of the protocol can be found in this r You can join at the [Discord](http://aave.com/discord) channel or at the [Governance Forum](https://governance.aave.com/) for asking questions about the protocol or talk about Aave with other peers. +## Getting Started + +You can install `@aave/protocol-v2` as an NPM package in your Hardhat, Buidler or Truffle project to import the contracts and interfaces: + +`npm install @aave/protocol-v2` + +Import at Solidity files: + +``` +import {ILendingPool} from "@aave/protocol-v2/contracts/interfaces/ILendingPool.sol"; + +contract Misc { + + function deposit(address pool, address token, address user, uint256 amount) { + ILendingPool(pool).deposit(token, amount, user, '0'); + {...} + } +} +``` + +The JSON artifacts with the ABI and Bytecode are also included into the bundled NPM package at `artifacts/` directory. + +Import JSON file via Node JS `require`: + +``` +const LendingPoolV2Artifact = require('@aave/protocol-v2/artifacts/contracts/protocol/lendingpool/LendingPool.sol/LendingPool.json'); + +// Log the ABI into console +console.log(LendingPoolV2Artifact.abi) +``` + ## Setup The repository uses Docker Compose to manage sensitive keys and load the configuration. Prior any action like test or deploy, you must run `docker-compose up` to start the `contracts-env` container, and then connect to the container console via `docker-compose exec contracts-env bash`. diff --git a/package.json b/package.json index ea016bca..d5cd3e16 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@aave/protocol-v2", - "version": "1.0.0", + "version": "1.0.1", "description": "Aave Protocol V2 smart contracts", "files": [ "contracts", From b2d70ec133e81128d8b9e5142cececeb91f12c36 Mon Sep 17 00:00:00 2001 From: David Racero Date: Tue, 26 Jan 2021 14:02:47 +0100 Subject: [PATCH 038/219] Run tests before publish at master --- .gitlab-ci.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index aef1554d..cea5dc05 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,7 +17,9 @@ test: after_script: - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down - + only: + - master + - merge_requests deploy-mainnet-fork: tags: - aave-build-runner @@ -29,6 +31,9 @@ deploy-mainnet-fork: after_script: - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down + only: + - master + - merge_requests certora-test: stage: checks @@ -45,6 +50,9 @@ certora-test: - certoraRun specs/harness/StableDebtTokenHarness.sol:StableDebtTokenHarness --solc_args "['--optimize']" --verify StableDebtTokenHarness:specs/StableDebtToken.spec --settings -assumeUnwindCond,-b=4 --cache StableDebtToken --cloud - certoraRun specs/harness/UserConfigurationHarness.sol --verify UserConfigurationHarness:specs/UserConfiguration.spec --solc_args "['--optimize']" --settings -useBitVectorTheory --cache UserConfiguration --cloud - certoraRun contracts/protocol/tokenization/VariableDebtToken.sol:VariableDebtToken specs/harness/LendingPoolHarnessForVariableDebtToken.sol --solc_args "['--optimize']" --link VariableDebtToken:POOL=LendingPoolHarnessForVariableDebtToken --verify VariableDebtToken:specs/VariableDebtToken.spec --settings -assumeUnwindCond,-useNonLinearArithmetic,-b=4 --cache VariableDebtToken --cloud + only: + - master + - merge_requests prepare: stage: prepare @@ -56,7 +64,6 @@ prepare: - docker push ${IMAGE} only: - master - - merge_requests publish: image: ${IMAGE} @@ -71,4 +78,3 @@ publish: - npm publish --access public only: - master - - merge_requests From 41b7adb4cc2927e1f35527a7e72ca765a730a307 Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 27 Jan 2021 10:49:30 +0100 Subject: [PATCH 039/219] Test super linter at Gitlab and Solidity --- .gitlab-ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b012440d..6a475c92 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,13 @@ stages: - checks +linter: + extends: .ci-cd-plugin-extension-github-action-super-linter + stage: checks + only: + - master + - merge_requests + test: stage: checks tags: From 89db02e79c1689a9ba0d00ab32041f6ddc014fb1 Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 27 Jan 2021 11:50:54 +0100 Subject: [PATCH 040/219] Add include --- .gitlab-ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6a475c92..3d9ecd9f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,11 @@ stages: - checks +include: + - project: 'guided-explorations/ci-cd-plugin-extensions/ci-cd-plugin-extension-github-action-super-linter' + file: '/ci-cd-plugin-extension-github-action-super-linter-gitlab-ci.yml' + ref: v0.1.4 + linter: extends: .ci-cd-plugin-extension-github-action-super-linter stage: checks From 6a503eb0a897124d8b9d126c915ffdf3e88343a9 Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 27 Jan 2021 15:43:34 +0100 Subject: [PATCH 041/219] Lint files. Add all ts and sol files to pre-commit. Add prettier format check to CI. --- .gitlab-ci.yml | 18 +- contracts/adapters/BaseUniswapAdapter.sol | 2 +- .../adapters/UniswapLiquiditySwapAdapter.sol | 37 +- contracts/adapters/UniswapRepayAdapter.sol | 10 +- .../openzeppelin/contracts/Context.sol | 4 +- .../openzeppelin/contracts/ERC20.sol | 6 +- .../BaseAdminUpgradeabilityProxy.sol | 3 +- .../BaseUpgradeabilityProxy.sol | 5 +- .../openzeppelin/upgradeability/Proxy.sol | 2 +- .../deployments/ATokensAndRatesHelper.sol | 5 +- contracts/interfaces/IUniswapV2Router02.sol | 16 +- contracts/misc/AaveOracle.sol | 2 +- contracts/misc/WalletBalanceProvider.sol | 3 +- .../mocks/flashloan/MockFlashLoanReceiver.sol | 5 +- contracts/mocks/oracle/LendingRateOracle.sol | 2 +- contracts/mocks/oracle/PriceOracle.sol | 2 +- .../DefaultReserveInterestRateStrategy.sol | 4 +- .../protocol/lendingpool/LendingPool.sol | 2 +- .../VersionedInitializable.sol | 10 +- .../configuration/ReserveConfiguration.sol | 41 +- .../configuration/UserConfiguration.sol | 9 +- .../protocol/libraries/logic/GenericLogic.sol | 11 +- helpers/etherscan-verification.ts | 8 +- helpers/misc-utils.ts | 18 +- helpers/mock-helpers.ts | 10 +- helpers/oracles-helpers.ts | 20 +- package-lock.json | 4814 ++++++----------- package.json | 3 +- tasks/dev/1_mock_tokens.ts | 6 +- tasks/dev/3_lending_pool.ts | 10 +- tasks/dev/4_oracles.ts | 18 +- tasks/dev/5_initialize.ts | 12 +- tasks/full/2_lending_pool.ts | 8 +- tasks/full/5_initialize.ts | 21 +- tasks/migrations/aave.dev.ts | 20 +- tasks/migrations/aave.mainnet.ts | 26 +- tasks/misc/print-contracts.ts | 4 +- tasks/misc/verify-sc.ts | 6 +- test/addresses-provider-registry.spec.ts | 28 +- test/atoken-modifiers.spec.ts | 16 +- test/atoken-transfer.spec.ts | 22 +- test/configurator.spec.ts | 64 +- test/flashloan.spec.ts | 65 +- test/helpers/scenario-engine.ts | 28 +- test/helpers/utils/calculations.ts | 1 - test/helpers/utils/math.ts | 25 +- test/lending-pool-addresses-provider.spec.ts | 39 +- test/liquidation-underlying.spec.ts | 38 +- test/mainnet/check-list.spec.ts | 82 +- test/pausable-functions.spec.ts | 38 +- test/scenario.spec.ts | 16 +- test/stable-token.spec.ts | 14 +- test/subgraph-scenarios.spec.ts | 16 +- test/upgradeability.spec.ts | 38 +- test/variable-debt-token.spec.ts | 14 +- test/weth-gateway.spec.ts | 80 +- 56 files changed, 2104 insertions(+), 3723 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3d9ecd9f..b30446a1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,17 +1,17 @@ stages: - checks -include: - - project: 'guided-explorations/ci-cd-plugin-extensions/ci-cd-plugin-extension-github-action-super-linter' - file: '/ci-cd-plugin-extension-github-action-super-linter-gitlab-ci.yml' - ref: v0.1.4 - linter: - extends: .ci-cd-plugin-extension-github-action-super-linter stage: checks - only: - - master - - merge_requests + tags: + - aave-build-runner + before_script: + - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml build + script: + - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env prettier:lint + after_script: + - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean + - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down test: stage: checks diff --git a/contracts/adapters/BaseUniswapAdapter.sol b/contracts/adapters/BaseUniswapAdapter.sol index 1a962473..5a866dba 100644 --- a/contracts/adapters/BaseUniswapAdapter.sol +++ b/contracts/adapters/BaseUniswapAdapter.sol @@ -441,7 +441,7 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt uint256 reserveDecimals = _getDecimals(reserveIn); address[] memory path = new address[](1); path[0] = reserveIn; - + return AmountCalc( amountIn, diff --git a/contracts/adapters/UniswapLiquiditySwapAdapter.sol b/contracts/adapters/UniswapLiquiditySwapAdapter.sol index 44745ad5..daac3547 100644 --- a/contracts/adapters/UniswapLiquiditySwapAdapter.sol +++ b/contracts/adapters/UniswapLiquiditySwapAdapter.sol @@ -187,16 +187,16 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter { * @param permitSignature List of struct containing the permit signature * @param useEthPath true if the swap needs to occur using ETH in the routing, false otherwise */ - + struct SwapLiquidityLocalVars { - address aToken; - uint256 aTokenInitiatorBalance; - uint256 amountToSwap; - uint256 receivedAmount; - uint256 flashLoanDebt; - uint256 amountToPull; + address aToken; + uint256 aTokenInitiatorBalance; + uint256 amountToSwap; + uint256 receivedAmount; + uint256 flashLoanDebt; + uint256 amountToPull; } - + function _swapLiquidity( address assetFrom, address assetTo, @@ -208,19 +208,22 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter { PermitSignature memory permitSignature, bool useEthPath ) internal { - SwapLiquidityLocalVars memory vars; - + vars.aToken = _getReserveData(assetFrom).aTokenAddress; vars.aTokenInitiatorBalance = IERC20(vars.aToken).balanceOf(initiator); - vars.amountToSwap = - swapAllBalance && vars.aTokenInitiatorBalance.sub(premium) <= amount - ? vars.aTokenInitiatorBalance.sub(premium) - : amount; + vars.amountToSwap = swapAllBalance && vars.aTokenInitiatorBalance.sub(premium) <= amount + ? vars.aTokenInitiatorBalance.sub(premium) + : amount; - vars.receivedAmount = - _swapExactTokensForTokens(assetFrom, assetTo, vars.amountToSwap, minAmountToReceive, useEthPath); + vars.receivedAmount = _swapExactTokensForTokens( + assetFrom, + assetTo, + vars.amountToSwap, + minAmountToReceive, + useEthPath + ); // Deposit new reserve IERC20(assetTo).safeApprove(address(LENDING_POOL), 0); @@ -277,4 +280,4 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter { useEthPath ); } -} \ No newline at end of file +} diff --git a/contracts/adapters/UniswapRepayAdapter.sol b/contracts/adapters/UniswapRepayAdapter.sol index c4e7817e..5d06494d 100644 --- a/contracts/adapters/UniswapRepayAdapter.sol +++ b/contracts/adapters/UniswapRepayAdapter.sol @@ -200,7 +200,13 @@ contract UniswapRepayAdapter is BaseUniswapAdapter { ); // Swap collateral asset to the debt asset - _swapTokensForExactTokens(collateralAsset, debtAsset, amounts[0], neededForFlashLoanDebt, useEthPath); + _swapTokensForExactTokens( + collateralAsset, + debtAsset, + amounts[0], + neededForFlashLoanDebt, + useEthPath + ); } else { // Pull aTokens from user _pullAToken( @@ -256,4 +262,4 @@ contract UniswapRepayAdapter is BaseUniswapAdapter { useEthPath ); } -} \ No newline at end of file +} diff --git a/contracts/dependencies/openzeppelin/contracts/Context.sol b/contracts/dependencies/openzeppelin/contracts/Context.sol index cfce1bfc..dc82ed76 100644 --- a/contracts/dependencies/openzeppelin/contracts/Context.sol +++ b/contracts/dependencies/openzeppelin/contracts/Context.sol @@ -12,11 +12,11 @@ pragma solidity 0.6.12; * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { - function _msgSender() internal virtual view returns (address payable) { + function _msgSender() internal view virtual returns (address payable) { return msg.sender; } - function _msgData() internal virtual view returns (bytes memory) { + function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } diff --git a/contracts/dependencies/openzeppelin/contracts/ERC20.sol b/contracts/dependencies/openzeppelin/contracts/ERC20.sol index e3946fb8..07fea73f 100644 --- a/contracts/dependencies/openzeppelin/contracts/ERC20.sol +++ b/contracts/dependencies/openzeppelin/contracts/ERC20.sol @@ -95,14 +95,14 @@ contract ERC20 is Context, IERC20 { /** * @dev See {IERC20-totalSupply}. */ - function totalSupply() public override view returns (uint256) { + function totalSupply() public view override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ - function balanceOf(address account) public override view returns (uint256) { + function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } @@ -124,9 +124,9 @@ contract ERC20 is Context, IERC20 { */ function allowance(address owner, address spender) public + view virtual override - view returns (uint256) { return _allowances[owner][spender]; diff --git a/contracts/dependencies/openzeppelin/upgradeability/BaseAdminUpgradeabilityProxy.sol b/contracts/dependencies/openzeppelin/upgradeability/BaseAdminUpgradeabilityProxy.sol index dd84184c..87e88957 100644 --- a/contracts/dependencies/openzeppelin/upgradeability/BaseAdminUpgradeabilityProxy.sol +++ b/contracts/dependencies/openzeppelin/upgradeability/BaseAdminUpgradeabilityProxy.sol @@ -24,7 +24,8 @@ contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy { * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ - bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; + bytes32 internal constant ADMIN_SLOT = + 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Modifier to check whether the `msg.sender` is the admin. diff --git a/contracts/dependencies/openzeppelin/upgradeability/BaseUpgradeabilityProxy.sol b/contracts/dependencies/openzeppelin/upgradeability/BaseUpgradeabilityProxy.sol index 8fb368f5..b0b82402 100644 --- a/contracts/dependencies/openzeppelin/upgradeability/BaseUpgradeabilityProxy.sol +++ b/contracts/dependencies/openzeppelin/upgradeability/BaseUpgradeabilityProxy.sol @@ -22,13 +22,14 @@ contract BaseUpgradeabilityProxy is Proxy { * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ - bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + bytes32 internal constant IMPLEMENTATION_SLOT = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation. * @return impl Address of the current implementation */ - function _implementation() internal override view returns (address impl) { + function _implementation() internal view override returns (address impl) { bytes32 slot = IMPLEMENTATION_SLOT; //solium-disable-next-line assembly { diff --git a/contracts/dependencies/openzeppelin/upgradeability/Proxy.sol b/contracts/dependencies/openzeppelin/upgradeability/Proxy.sol index 0148899b..ab20b9ad 100644 --- a/contracts/dependencies/openzeppelin/upgradeability/Proxy.sol +++ b/contracts/dependencies/openzeppelin/upgradeability/Proxy.sol @@ -20,7 +20,7 @@ abstract contract Proxy { /** * @return The Address of the implementation. */ - function _implementation() internal virtual view returns (address); + function _implementation() internal view virtual returns (address); /** * @dev Delegates execution to an implementation contract. diff --git a/contracts/deployments/ATokensAndRatesHelper.sol b/contracts/deployments/ATokensAndRatesHelper.sol index a29dc6f2..0593178a 100644 --- a/contracts/deployments/ATokensAndRatesHelper.sol +++ b/contracts/deployments/ATokensAndRatesHelper.sol @@ -112,10 +112,7 @@ contract ATokensAndRatesHelper is Ownable { liquidationBonuses[i] ); - configurator.enableBorrowingOnReserve( - assets[i], - stableBorrowingEnabled[i] - ); + configurator.enableBorrowingOnReserve(assets[i], stableBorrowingEnabled[i]); configurator.setReserveFactor(assets[i], reserveFactors[i]); } } diff --git a/contracts/interfaces/IUniswapV2Router02.sol b/contracts/interfaces/IUniswapV2Router02.sol index af0f8280..1b1dc475 100644 --- a/contracts/interfaces/IUniswapV2Router02.sol +++ b/contracts/interfaces/IUniswapV2Router02.sol @@ -11,14 +11,20 @@ interface IUniswapV2Router02 { ) external returns (uint256[] memory amounts); function swapTokensForExactTokens( - uint amountOut, - uint amountInMax, + uint256 amountOut, + uint256 amountInMax, address[] calldata path, address to, - uint deadline + uint256 deadline ) external returns (uint256[] memory amounts); - function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); + function getAmountsOut(uint256 amountIn, address[] calldata path) + external + view + returns (uint256[] memory amounts); - function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); + function getAmountsIn(uint256 amountOut, address[] calldata path) + external + view + returns (uint256[] memory amounts); } diff --git a/contracts/misc/AaveOracle.sol b/contracts/misc/AaveOracle.sol index b34d16b8..0cb8e180 100644 --- a/contracts/misc/AaveOracle.sol +++ b/contracts/misc/AaveOracle.sol @@ -80,7 +80,7 @@ contract AaveOracle is IPriceOracleGetter, Ownable { /// @notice Gets an asset price by address /// @param asset The asset address - function getAssetPrice(address asset) public override view returns (uint256) { + function getAssetPrice(address asset) public view override returns (uint256) { IChainlinkAggregator source = assetsSources[asset]; if (asset == WETH) { diff --git a/contracts/misc/WalletBalanceProvider.sol b/contracts/misc/WalletBalanceProvider.sol index cd4a81ce..3d4a9288 100644 --- a/contracts/misc/WalletBalanceProvider.sol +++ b/contracts/misc/WalletBalanceProvider.sol @@ -93,7 +93,8 @@ contract WalletBalanceProvider { uint256[] memory balances = new uint256[](reservesWithEth.length); for (uint256 j = 0; j < reserves.length; j++) { - DataTypes.ReserveConfigurationMap memory configuration = pool.getConfiguration(reservesWithEth[j]); + DataTypes.ReserveConfigurationMap memory configuration = + pool.getConfiguration(reservesWithEth[j]); (bool isActive, , , ) = configuration.getFlagsMemory(); diff --git a/contracts/mocks/flashloan/MockFlashLoanReceiver.sol b/contracts/mocks/flashloan/MockFlashLoanReceiver.sol index a0b3f8ca..9bf29730 100644 --- a/contracts/mocks/flashloan/MockFlashLoanReceiver.sol +++ b/contracts/mocks/flashloan/MockFlashLoanReceiver.sol @@ -68,9 +68,8 @@ contract MockFlashLoanReceiver is FlashLoanReceiverBase { 'Invalid balance for the contract' ); - uint256 amountToReturn = (_amountToApprove != 0) - ? _amountToApprove - : amounts[i].add(premiums[i]); + uint256 amountToReturn = + (_amountToApprove != 0) ? _amountToApprove : amounts[i].add(premiums[i]); //execution does not fail - mint tokens and return them to the _destination token.mint(premiums[i]); diff --git a/contracts/mocks/oracle/LendingRateOracle.sol b/contracts/mocks/oracle/LendingRateOracle.sol index 045a1d4c..44fe8aa1 100644 --- a/contracts/mocks/oracle/LendingRateOracle.sol +++ b/contracts/mocks/oracle/LendingRateOracle.sol @@ -8,7 +8,7 @@ contract LendingRateOracle is ILendingRateOracle, Ownable { mapping(address => uint256) borrowRates; mapping(address => uint256) liquidityRates; - function getMarketBorrowRate(address _asset) external override view returns (uint256) { + function getMarketBorrowRate(address _asset) external view override returns (uint256) { return borrowRates[_asset]; } diff --git a/contracts/mocks/oracle/PriceOracle.sol b/contracts/mocks/oracle/PriceOracle.sol index 183eff50..fe04a044 100644 --- a/contracts/mocks/oracle/PriceOracle.sol +++ b/contracts/mocks/oracle/PriceOracle.sol @@ -10,7 +10,7 @@ contract PriceOracle is IPriceOracle { event AssetPriceUpdated(address _asset, uint256 _price, uint256 timestamp); event EthPriceUpdated(uint256 _price, uint256 timestamp); - function getAssetPrice(address _asset) external override view returns (uint256) { + function getAssetPrice(address _asset) external view override returns (uint256) { return prices[_asset]; } diff --git a/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol b/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol index 6f45004c..c2584a22 100644 --- a/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol +++ b/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol @@ -139,9 +139,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { vars.currentLiquidityRate = 0; uint256 utilizationRate = - vars.totalDebt == 0 - ? 0 - : vars.totalDebt.rayDiv(availableLiquidity.add(vars.totalDebt)); + vars.totalDebt == 0 ? 0 : vars.totalDebt.rayDiv(availableLiquidity.add(vars.totalDebt)); vars.currentStableBorrowRate = ILendingRateOracle(addressesProvider.getLendingRateOracle()) .getMarketBorrowRate(reserve); diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 7c48f237..345c910a 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -144,7 +144,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage address asset, uint256 amount, address to - ) external override whenNotPaused returns (uint256) { + ) external override whenNotPaused returns (uint256) { DataTypes.ReserveData storage reserve = _reserves[asset]; address aToken = reserve.aTokenAddress; diff --git a/contracts/protocol/libraries/aave-upgradeability/VersionedInitializable.sol b/contracts/protocol/libraries/aave-upgradeability/VersionedInitializable.sol index f2b73b8e..b8e356ae 100644 --- a/contracts/protocol/libraries/aave-upgradeability/VersionedInitializable.sol +++ b/contracts/protocol/libraries/aave-upgradeability/VersionedInitializable.sol @@ -50,14 +50,14 @@ abstract contract VersionedInitializable { } /** - * @dev returns the revision number of the contract - * Needs to be defined in the inherited class as a constant. - **/ + * @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); /** - * @dev Returns true if and only if the function is running in the constructor - **/ + * @dev Returns true if and only if the function is running in the constructor + **/ function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not diff --git a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol index 60076a6f..5649a580 100644 --- a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol @@ -90,7 +90,10 @@ library ReserveConfiguration { * @param self The reserve configuration * @param bonus The new liquidation bonus **/ - function setLiquidationBonus(DataTypes.ReserveConfigurationMap memory self, uint256 bonus) internal pure { + function setLiquidationBonus(DataTypes.ReserveConfigurationMap memory self, uint256 bonus) + internal + pure + { require(bonus <= MAX_VALID_LIQUIDATION_BONUS, Errors.RC_INVALID_LIQ_BONUS); self.data = @@ -116,7 +119,10 @@ library ReserveConfiguration { * @param self The reserve configuration * @param decimals The decimals **/ - function setDecimals(DataTypes.ReserveConfigurationMap memory self, uint256 decimals) internal pure { + function setDecimals(DataTypes.ReserveConfigurationMap memory self, uint256 decimals) + internal + pure + { require(decimals <= MAX_VALID_DECIMALS, Errors.RC_INVALID_DECIMALS); self.data = (self.data & DECIMALS_MASK) | (decimals << RESERVE_DECIMALS_START_BIT_POSITION); @@ -127,7 +133,11 @@ library ReserveConfiguration { * @param self The reserve configuration * @return The decimals of the asset **/ - function getDecimals(DataTypes.ReserveConfigurationMap storage self) internal view returns (uint256) { + function getDecimals(DataTypes.ReserveConfigurationMap storage self) + internal + view + returns (uint256) + { return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION; } @@ -176,7 +186,10 @@ library ReserveConfiguration { * @param self The reserve configuration * @param enabled True if the borrowing needs to be enabled, false otherwise **/ - function setBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled) internal pure { + function setBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled) + internal + pure + { self.data = (self.data & BORROWING_MASK) | (uint256(enabled ? 1 : 0) << BORROWING_ENABLED_START_BIT_POSITION); @@ -187,7 +200,11 @@ library ReserveConfiguration { * @param self The reserve configuration * @return The borrowing state **/ - function getBorrowingEnabled(DataTypes.ReserveConfigurationMap storage self) internal view returns (bool) { + function getBorrowingEnabled(DataTypes.ReserveConfigurationMap storage self) + internal + view + returns (bool) + { return (self.data & ~BORROWING_MASK) != 0; } @@ -196,10 +213,10 @@ library ReserveConfiguration { * @param self The reserve configuration * @param enabled True if the stable rate borrowing needs to be enabled, false otherwise **/ - function setStableRateBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled) - internal - pure - { + function setStableRateBorrowingEnabled( + DataTypes.ReserveConfigurationMap memory self, + bool enabled + ) internal pure { self.data = (self.data & STABLE_BORROWING_MASK) | (uint256(enabled ? 1 : 0) << STABLE_BORROWING_ENABLED_START_BIT_POSITION); @@ -239,7 +256,11 @@ library ReserveConfiguration { * @param self The reserve configuration * @return The reserve factor **/ - function getReserveFactor(DataTypes.ReserveConfigurationMap storage self) internal view returns (uint256) { + function getReserveFactor(DataTypes.ReserveConfigurationMap storage self) + internal + view + returns (uint256) + { return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION; } diff --git a/contracts/protocol/libraries/configuration/UserConfiguration.sol b/contracts/protocol/libraries/configuration/UserConfiguration.sol index b56f6140..2994f05d 100644 --- a/contracts/protocol/libraries/configuration/UserConfiguration.sol +++ b/contracts/protocol/libraries/configuration/UserConfiguration.sol @@ -53,11 +53,10 @@ library UserConfiguration { * @param reserveIndex The index of the reserve in the bitmap * @return True if the user has been using a reserve for borrowing or as collateral, false otherwise **/ - function isUsingAsCollateralOrBorrowing(DataTypes.UserConfigurationMap memory self, uint256 reserveIndex) - internal - pure - returns (bool) - { + function isUsingAsCollateralOrBorrowing( + DataTypes.UserConfigurationMap memory self, + uint256 reserveIndex + ) internal pure returns (bool) { require(reserveIndex < 128, Errors.UL_INVALID_INDEX); return (self.data >> (reserveIndex * 2)) & 3 != 0; } diff --git a/contracts/protocol/libraries/logic/GenericLogic.sol b/contracts/protocol/libraries/logic/GenericLogic.sol index e921ec52..d4081dda 100644 --- a/contracts/protocol/libraries/logic/GenericLogic.sol +++ b/contracts/protocol/libraries/logic/GenericLogic.sol @@ -65,7 +65,7 @@ library GenericLogic { if (!userConfig.isBorrowingAny() || !userConfig.isUsingAsCollateral(reservesData[asset].id)) { return true; } - + balanceDecreaseAllowedLocalVars memory vars; (, vars.liquidationThreshold, , vars.decimals, ) = reservesData[asset] @@ -73,7 +73,7 @@ library GenericLogic { .getParams(); if (vars.liquidationThreshold == 0) { - return true; + return true; } ( @@ -213,9 +213,7 @@ library GenericLogic { } } - vars.avgLtv = vars.totalCollateralInETH > 0 - ? vars.avgLtv.div(vars.totalCollateralInETH) - : 0; + vars.avgLtv = vars.totalCollateralInETH > 0 ? vars.avgLtv.div(vars.totalCollateralInETH) : 0; vars.avgLiquidationThreshold = vars.totalCollateralInETH > 0 ? vars.avgLiquidationThreshold.div(vars.totalCollateralInETH) : 0; @@ -265,8 +263,7 @@ library GenericLogic { uint256 totalDebtInETH, uint256 ltv ) internal pure returns (uint256) { - - uint256 availableBorrowsETH = totalCollateralInETH.percentMul(ltv); + uint256 availableBorrowsETH = totalCollateralInETH.percentMul(ltv); if (availableBorrowsETH < totalDebtInETH) { return 0; diff --git a/helpers/etherscan-verification.ts b/helpers/etherscan-verification.ts index 902cb2fe..ddbf80e4 100644 --- a/helpers/etherscan-verification.ts +++ b/helpers/etherscan-verification.ts @@ -1,7 +1,7 @@ -import {exit} from 'process'; +import { exit } from 'process'; import fs from 'fs'; -import {file} from 'tmp-promise'; -import {DRE} from './misc-utils'; +import { file } from 'tmp-promise'; +import { DRE } from './misc-utils'; const fatalErrors = [ `The address provided as argument contains a contract, but its bytecode`, @@ -43,7 +43,7 @@ export const verifyContract = async ( const msDelay = 3000; const times = 4; // Write a temporal file to host complex parameters for buidler-etherscan https://github.com/nomiclabs/buidler/tree/development/packages/buidler-etherscan#complex-arguments - const {fd, path, cleanup} = await file({ + const { fd, path, cleanup } = await file({ prefix: 'verify-params-', postfix: '.js', }); diff --git a/helpers/misc-utils.ts b/helpers/misc-utils.ts index a3408009..6d7bb185 100644 --- a/helpers/misc-utils.ts +++ b/helpers/misc-utils.ts @@ -2,13 +2,13 @@ import BigNumber from 'bignumber.js'; import BN = require('bn.js'); import low from 'lowdb'; import FileSync from 'lowdb/adapters/FileSync'; -import {WAD} from './constants'; -import {Wallet, ContractTransaction} from 'ethers'; -import {HardhatRuntimeEnvironment} from 'hardhat/types'; -import {BuidlerRuntimeEnvironment} from '@nomiclabs/buidler/types'; -import {tEthereumAddress} from './types'; -import {isAddress} from 'ethers/lib/utils'; -import {isZeroAddress} from 'ethereumjs-util'; +import { WAD } from './constants'; +import { Wallet, ContractTransaction } from 'ethers'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { BuidlerRuntimeEnvironment } from '@nomiclabs/buidler/types'; +import { tEthereumAddress } from './types'; +import { isAddress } from 'ethers/lib/utils'; +import { isZeroAddress } from 'ethereumjs-util'; export const toWad = (value: string | number) => new BigNumber(value).times(WAD).toFixed(); @@ -49,10 +49,10 @@ export const increaseTime = async (secondsToIncrease: number) => { export const waitForTx = async (tx: ContractTransaction) => await tx.wait(1); -export const filterMapBy = (raw: {[key: string]: any}, fn: (key: string) => boolean) => +export const filterMapBy = (raw: { [key: string]: any }, fn: (key: string) => boolean) => Object.keys(raw) .filter(fn) - .reduce<{[key: string]: any}>((obj, key) => { + .reduce<{ [key: string]: any }>((obj, key) => { obj[key] = raw[key]; return obj; }, {}); diff --git a/helpers/mock-helpers.ts b/helpers/mock-helpers.ts index 5989216d..11859d97 100644 --- a/helpers/mock-helpers.ts +++ b/helpers/mock-helpers.ts @@ -1,10 +1,10 @@ -import {tEthereumAddress} from './types'; -import {MockAggregator} from '../types/MockAggregator'; -import {MockTokenMap} from './contracts-helpers'; +import { tEthereumAddress } from './types'; +import { MockAggregator } from '../types/MockAggregator'; +import { MockTokenMap } from './contracts-helpers'; export const getAllTokenAddresses = (mockTokens: MockTokenMap) => Object.entries(mockTokens).reduce( - (accum: {[tokenSymbol: string]: tEthereumAddress}, [tokenSymbol, tokenContract]) => ({ + (accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, tokenContract]) => ({ ...accum, [tokenSymbol]: tokenContract.address, }), @@ -14,7 +14,7 @@ export const getAllAggregatorsAddresses = (mockAggregators: { [tokenSymbol: string]: MockAggregator; }) => Object.entries(mockAggregators).reduce( - (accum: {[tokenSymbol: string]: tEthereumAddress}, [tokenSymbol, aggregator]) => ({ + (accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, aggregator]) => ({ ...accum, [tokenSymbol]: aggregator.address, }), diff --git a/helpers/oracles-helpers.ts b/helpers/oracles-helpers.ts index 45cec5e2..9fd2ba44 100644 --- a/helpers/oracles-helpers.ts +++ b/helpers/oracles-helpers.ts @@ -7,16 +7,16 @@ import { SymbolMap, } from './types'; -import {LendingRateOracle} from '../types/LendingRateOracle'; -import {PriceOracle} from '../types/PriceOracle'; -import {MockAggregator} from '../types/MockAggregator'; -import {deployMockAggregator} from './contracts-deployments'; -import {chunk, waitForTx} from './misc-utils'; -import {getStableAndVariableTokensHelper} from './contracts-getters'; +import { LendingRateOracle } from '../types/LendingRateOracle'; +import { PriceOracle } from '../types/PriceOracle'; +import { MockAggregator } from '../types/MockAggregator'; +import { deployMockAggregator } from './contracts-deployments'; +import { chunk, waitForTx } from './misc-utils'; +import { getStableAndVariableTokensHelper } from './contracts-getters'; export const setInitialMarketRatesInRatesOracleByHelper = async ( marketRates: iMultiPoolsAssets, - assetsAddresses: {[x: string]: tEthereumAddress}, + assetsAddresses: { [x: string]: tEthereumAddress }, lendingRateOracleInstance: LendingRateOracle, admin: tEthereumAddress ) => { @@ -24,7 +24,7 @@ export const setInitialMarketRatesInRatesOracleByHelper = async ( const assetAddresses: string[] = []; const borrowRates: string[] = []; const symbols: string[] = []; - for (const [assetSymbol, {borrowRate}] of Object.entries(marketRates) as [ + for (const [assetSymbol, { borrowRate }] of Object.entries(marketRates) as [ string, IMarketRates ][]) { @@ -99,7 +99,7 @@ export const setAssetPricesInOracle = async ( }; export const deployMockAggregators = async (initialPrices: SymbolMap, verify?: boolean) => { - const aggregators: {[tokenSymbol: string]: MockAggregator} = {}; + const aggregators: { [tokenSymbol: string]: MockAggregator } = {}; for (const tokenContractName of Object.keys(initialPrices)) { if (tokenContractName !== 'ETH') { const priceIndex = Object.keys(initialPrices).findIndex( @@ -116,7 +116,7 @@ export const deployAllMockAggregators = async ( initialPrices: iAssetAggregatorBase, verify?: boolean ) => { - const aggregators: {[tokenSymbol: string]: MockAggregator} = {}; + const aggregators: { [tokenSymbol: string]: MockAggregator } = {}; for (const tokenContractName of Object.keys(initialPrices)) { if (tokenContractName !== 'ETH') { const priceIndex = Object.keys(initialPrices).findIndex( diff --git a/package-lock.json b/package-lock.json index 3ea8f296..dfdeb1a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2908,15 +2908,6 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, - "bufferutil": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.2.tgz", - "integrity": "sha512-AtnG3W6M8B2n4xDQ5R+70EXvOpnXsFYg/AK2yTZd+HQ/oxAdz+GI+DvjmhBw3L0ole+LJ0ngqY4JMbDzkfNzhA==", - "dev": true, - "requires": { - "node-gyp-build": "^4.2.0" - } - }, "buidler-typechain": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/buidler-typechain/-/buidler-typechain-0.1.1.tgz", @@ -3111,33 +3102,6 @@ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, - "cids": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", - "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", - "dev": true, - "optional": true, - "requires": { - "buffer": "^5.5.0", - "class-is": "^1.1.0", - "multibase": "~0.6.0", - "multicodec": "^1.0.0", - "multihashes": "~0.4.15" - }, - "dependencies": { - "multicodec": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", - "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", - "dev": true, - "optional": true, - "requires": { - "buffer": "^5.6.0", - "varint": "^5.0.0" - } - } - } - }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3148,13 +3112,6 @@ "safe-buffer": "^5.0.1" } }, - "class-is": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", - "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", - "dev": true, - "optional": true - }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -3257,6 +3214,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "requires": { "color-name": "1.1.3" } @@ -3264,7 +3222,8 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true }, "colors": { "version": "1.4.0", @@ -3398,18 +3357,6 @@ } } }, - "content-hash": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", - "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", - "dev": true, - "optional": true, - "requires": { - "cids": "^0.7.1", - "multicodec": "^0.5.5", - "multihashes": "^0.4.15" - } - }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", @@ -6352,6 +6299,148 @@ "@ethersproject/strings": ">=5.0.0-beta.130" } }, + "@ethersproject/address": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.5.tgz", + "integrity": "sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/rlp": "^5.0.3", + "bn.js": "^4.4.0" + } + }, + "@ethersproject/bignumber": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.8.tgz", + "integrity": "sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "bn.js": "^4.4.0" + } + }, + "@ethersproject/bytes": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.5.tgz", + "integrity": "sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/constants": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.5.tgz", + "integrity": "sha512-foaQVmxp2+ik9FrLUCtVrLZCj4M3Ibgkqvh+Xw/vFRSerkjVSYePApaVE5essxhoSlF1U9oXfWY09QI2AXtgKA==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bignumber": "^5.0.7" + } + }, + "@ethersproject/hash": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.5.tgz", + "integrity": "sha512-GpI80/h2HDpfNKpCZoxQJCjOQloGnlD5hM1G+tZe8FQDJhEvFjJoPDuWv+NaYjJfOciKS2Axqc4Q4WamdLoUgg==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/strings": "^5.0.4" + } + }, + "@ethersproject/keccak256": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.4.tgz", + "integrity": "sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.4", + "js-sha3": "0.5.7" + } + }, + "@ethersproject/logger": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.6.tgz", + "integrity": "sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ==", + "dev": true, + "optional": true + }, + "@ethersproject/properties": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.4.tgz", + "integrity": "sha512-UdyX3GqBxFt15B0uSESdDNmhvEbK3ACdDXl2soshoPcneXuTswHDeA0LoPlnaZzhbgk4p6jqb4GMms5C26Qu6A==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/rlp": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.4.tgz", + "integrity": "sha512-5qrrZad7VTjofxSsm7Zg/7Dr4ZOln4S2CqiDdOuTv6MBKnXj0CiBojXyuDy52M8O3wxH0CyE924hXWTDV1PQWQ==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/signing-key": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.5.tgz", + "integrity": "sha512-Z1wY7JC1HVO4CvQWY2TyTTuAr8xK3bJijZw1a9G92JEmKdv1j255R/0YLBBcFTl2J65LUjtXynNJ2GbArPGi5g==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "elliptic": "6.5.3" + } + }, + "@ethersproject/strings": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.5.tgz", + "integrity": "sha512-JED6WaIV00xM/gvj8vSnd+0VWtDYdidTmavFRCTQakqfz+4tDo6Jz5LHgG+dd45h7ah7ykCHW0C7ZXWEDROCXQ==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/transactions": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.6.tgz", + "integrity": "sha512-htsFhOD+NMBxx676A8ehSuwVV49iqpSB+CkjPZ02tpNew0K6p8g0CZ46Z1ZP946gIHAU80xQ0NACHYrjIUaCFA==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/rlp": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4" + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -6369,14 +6458,6 @@ "defer-to-connect": "^1.0.1" } }, - "@types/bignumber.js": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/bignumber.js/-/bignumber.js-5.0.0.tgz", - "integrity": "sha512-0DH7aPGCClywOFaxxjE6UwpN2kQYe9LwuDQMv+zYA97j5GkOMo8e66LYT+a8JYU7jfmUFRZLa9KycxHDsKXJCA==", - "requires": { - "bignumber.js": "*" - } - }, "@types/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", @@ -6410,53 +6491,11 @@ "@types/node": "*" } }, - "@web3-js/scrypt-shim": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz", - "integrity": "sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw==", - "requires": { - "scryptsy": "^2.1.0", - "semver": "^6.3.0" - }, - "dependencies": { - "scryptsy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz", - "integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==" - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "@web3-js/websocket": { - "version": "1.0.30", - "resolved": "https://registry.npmjs.org/@web3-js/websocket/-/websocket-1.0.30.tgz", - "integrity": "sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA==", - "requires": { - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "nan": "^2.14.0", - "typedarray-to-buffer": "^3.1.5", - "yaeti": "^0.0.6" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true }, "abstract-leveldown": { "version": "3.0.0", @@ -6497,112 +6536,32 @@ "uri-js": "^4.2.2" } }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" - }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "requires": { - "make-iterator": "^1.0.0" - } + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "requires": { - "make-iterator": "^1.0.0" - } + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true }, "array-flatten": { "version": "1.1.1", @@ -6611,63 +6570,11 @@ "dev": true, "optional": true }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true }, "asn1": { "version": "0.2.4", @@ -6700,7 +6607,8 @@ "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true }, "async": { "version": "2.6.2", @@ -6711,22 +6619,6 @@ "lodash": "^4.17.11" } }, - "async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" - }, "async-eventemitter": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", @@ -6742,14 +6634,6 @@ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "dev": true }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "requires": { - "async-done": "^1.2.2" - } - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -6759,7 +6643,8 @@ "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true }, "aws-sign2": { "version": "0.7.0", @@ -6784,6 +6669,12 @@ "js-tokens": "^3.0.2" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -6809,6 +6700,15 @@ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", "dev": true }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -6853,16 +6753,22 @@ "ms": "2.0.0" } }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", "dev": true } } @@ -6888,12 +6794,6 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true } } }, @@ -7406,21 +7306,6 @@ "source-map-support": "^0.4.15" }, "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "source-map-support": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", @@ -7481,6 +7366,12 @@ "ms": "2.0.0" } }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -7499,6 +7390,14 @@ "esutils": "^2.0.2", "lodash": "^4.17.4", "to-fast-properties": "^1.0.3" + }, + "dependencies": { + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + } } }, "babelify": { @@ -7517,22 +7416,6 @@ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, "backoff": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", @@ -7545,12 +7428,14 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, "requires": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", @@ -7565,35 +7450,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "^1.0.0" } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } } } }, @@ -7601,6 +7461,7 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", + "dev": true, "requires": { "safe-buffer": "^5.0.1" } @@ -7608,7 +7469,8 @@ "base64-js": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -7630,20 +7492,9 @@ "bignumber.js": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", - "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "requires": { - "file-uri-to-path": "1.0.0" - } + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", + "dev": true, + "optional": true }, "bip39": { "version": "2.5.0", @@ -7658,66 +7509,6 @@ "unorm": "^1.3.3" } }, - "bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "bl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - } - } - }, "blakejs": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", @@ -7734,7 +7525,8 @@ "bn.js": { "version": "4.11.9", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true }, "body-parser": { "version": "1.19.0", @@ -7785,44 +7577,23 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" - } - } - }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true }, "browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, "requires": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -7921,6 +7692,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "dev": true, "requires": { "base-x": "^3.0.2" } @@ -7929,6 +7701,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, "requires": { "bs58": "^4.0.0", "create-hash": "^1.1.0", @@ -7939,44 +7712,17 @@ "version": "5.6.0", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dev": true, "requires": { "base64-js": "^1.0.2", "ieee754": "^1.1.4" } }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=" - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" - }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true }, "buffer-to-arraybuffer": { "version": "0.0.5", @@ -7988,7 +7734,25 @@ "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "bufferutil": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", + "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==", + "dev": true, + "requires": { + "node-gyp-build": "~3.7.0" + }, + "dependencies": { + "node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "dev": true + } + } }, "bytes": { "version": "3.1.0", @@ -8020,6 +7784,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, "requires": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", @@ -8048,16 +7813,6 @@ "responselike": "^1.0.2" }, "dependencies": { - "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", - "dev": true, - "optional": true, - "requires": { - "pump": "^3.0.0" - } - }, "lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -8097,11 +7852,6 @@ } } }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" - }, "caniuse-lite": { "version": "1.0.30001146", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001146.tgz", @@ -8118,6 +7868,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -8133,24 +7884,6 @@ "functional-red-black-tree": "^1.0.1" } }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, "chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -8158,19 +7891,61 @@ "dev": true, "optional": true }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cids": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", + "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", + "dev": true, + "optional": true, + "requires": { + "buffer": "^5.5.0", + "class-is": "^1.1.0", + "multibase": "~0.6.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.15" + }, + "dependencies": { + "multicodec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", + "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", + "dev": true, + "optional": true, + "requires": { + "buffer": "^5.6.0", + "varint": "^5.0.0" + } + } + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, + "class-is": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", + "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", + "dev": true, + "optional": true + }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, "requires": { "arr-union": "^3.1.0", "define-property": "^0.2.5", @@ -8181,29 +7956,82 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=" + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true } } }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, "clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true }, "clone-response": { "version": "1.0.2", @@ -8215,83 +8043,30 @@ "mimic-response": "^1.0.0" } }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" - }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, "requires": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" } }, - "color-support": { + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true }, "combined-stream": { "version": "1.0.8", @@ -8302,64 +8077,28 @@ "delayed-stream": "~1.0.0" } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, "requires": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "content-disposition": { @@ -8381,6 +8120,18 @@ } } }, + "content-hash": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", + "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", + "dev": true, + "optional": true, + "requires": { + "cids": "^0.7.1", + "multicodec": "^0.5.5", + "multihashes": "^0.4.15" + } + }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", @@ -8392,6 +8143,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, "requires": { "safe-buffer": "~5.1.1" }, @@ -8399,7 +8151,8 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, @@ -8427,16 +8180,8 @@ "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" - }, - "copy-props": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", - "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", - "requires": { - "each-props": "^1.3.0", - "is-plain-object": "^2.0.1" - } + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true }, "core-js": { "version": "2.6.11", @@ -8453,7 +8198,8 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "cors": { "version": "2.8.5", @@ -8481,6 +8227,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, "requires": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -8493,6 +8240,7 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, "requires": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -8536,6 +8284,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, "requires": { "es5-ext": "^0.10.50", "type": "^1.0.1" @@ -8559,37 +8308,11 @@ "ms": "^2.1.1" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "decompress": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", - "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", - "requires": { - "decompress-tar": "^4.0.0", - "decompress-tarbz2": "^4.0.0", - "decompress-targz": "^4.0.0", - "decompress-unzip": "^4.0.1", - "graceful-fs": "^4.1.10", - "make-dir": "^1.0.0", - "pify": "^2.3.0", - "strip-dirs": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true }, "decompress-response": { "version": "3.3.0", @@ -8601,77 +8324,6 @@ "mimic-response": "^1.0.0" } }, - "decompress-tar": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", - "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", - "requires": { - "file-type": "^5.2.0", - "is-stream": "^1.1.0", - "tar-stream": "^1.5.2" - } - }, - "decompress-tarbz2": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", - "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", - "requires": { - "decompress-tar": "^4.1.0", - "file-type": "^6.1.0", - "is-stream": "^1.1.0", - "seek-bzip": "^1.0.5", - "unbzip2-stream": "^1.0.9" - }, - "dependencies": { - "file-type": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", - "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" - } - } - }, - "decompress-targz": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", - "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", - "requires": { - "decompress-tar": "^4.1.1", - "file-type": "^5.2.0", - "is-stream": "^1.1.0" - } - }, - "decompress-unzip": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", - "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", - "requires": { - "file-type": "^3.8.0", - "get-stream": "^2.2.0", - "pify": "^2.3.0", - "yauzl": "^2.4.2" - }, - "dependencies": { - "file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" - }, - "get-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", - "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", - "requires": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, "deep-equal": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", @@ -8684,36 +8336,8 @@ "object-is": "^1.0.1", "object-keys": "^1.1.1", "regexp.prototype.flags": "^1.2.0" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } } }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "requires": { - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=" - }, "defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -8725,6 +8349,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", + "dev": true, "requires": { "abstract-leveldown": "~5.0.0", "inherits": "^2.0.3" @@ -8734,6 +8359,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, "requires": { "xtend": "~4.0.0" } @@ -8744,52 +8370,19 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, "requires": { "object-keys": "^1.0.12" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - } } }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } } }, "defined": { @@ -8829,11 +8422,6 @@ "dev": true, "optional": true }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" - }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", @@ -8870,16 +8458,6 @@ "minimatch": "^3.0.4" } }, - "drbg.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", - "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", - "requires": { - "browserify-aes": "^1.0.6", - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4" - } - }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -8887,60 +8465,6 @@ "dev": true, "optional": true }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -8968,6 +8492,7 @@ "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", @@ -9033,6 +8558,7 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "requires": { "once": "^1.4.0" } @@ -9041,22 +8567,16 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, "requires": { "prr": "~1.0.1" } }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, "es-abstract": { "version": "1.17.7", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", @@ -9069,19 +8589,13 @@ "object.assign": "^4.1.1", "string.prototype.trimend": "^1.0.1", "string.prototype.trimstart": "^1.0.1" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - } } }, "es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -9092,6 +8606,7 @@ "version": "0.10.53", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.3", @@ -9102,6 +8617,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, "requires": { "d": "1", "es5-ext": "^0.10.35", @@ -9112,22 +8628,12 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, "requires": { "d": "^1.0.1", "ext": "^1.1.2" } }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -9138,7 +8644,8 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "esutils": { "version": "2.0.3", @@ -9210,15 +8717,6 @@ "requires": { "idna-uts46-hx": "^2.3.1", "js-sha3": "^0.5.7" - }, - "dependencies": { - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true, - "optional": true - } } }, "eth-json-rpc-infura": { @@ -9272,12 +8770,6 @@ "abstract-leveldown": "~2.6.0" } }, - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true - }, "ethereumjs-account": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", @@ -9300,6 +8792,14 @@ "ethereumjs-tx": "^1.2.2", "ethereumjs-util": "^5.0.0", "merkle-patricia-tree": "^2.1.2" + }, + "dependencies": { + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", + "dev": true + } } }, "ethereumjs-tx": { @@ -9310,14 +8810,6 @@ "requires": { "ethereum-common": "^0.0.18", "ethereumjs-util": "^5.0.0" - }, - "dependencies": { - "ethereum-common": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=", - "dev": true - } } }, "ethereumjs-util": { @@ -9506,6 +8998,37 @@ "xtend": "~4.0.0" } }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "requires": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "requires": { + "xtend": "~4.0.0" + } + } + } + }, "merkle-patricia-tree": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", @@ -9536,6 +9059,18 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -9661,12 +9196,6 @@ "abstract-leveldown": "~2.6.0" } }, - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true - }, "ethereumjs-account": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", @@ -9689,6 +9218,14 @@ "ethereumjs-tx": "^1.2.2", "ethereumjs-util": "^5.0.0", "merkle-patricia-tree": "^2.1.2" + }, + "dependencies": { + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", + "dev": true + } } }, "ethereumjs-tx": { @@ -9699,14 +9236,6 @@ "requires": { "ethereum-common": "^0.0.18", "ethereumjs-util": "^5.0.0" - }, - "dependencies": { - "ethereum-common": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=", - "dev": true - } } }, "ethereumjs-util": { @@ -9895,6 +9424,37 @@ "xtend": "~4.0.0" } }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "requires": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "requires": { + "xtend": "~4.0.0" + } + } + } + }, "merkle-patricia-tree": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", @@ -9925,6 +9485,18 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -10186,6 +9758,37 @@ "xtend": "~4.0.0" } }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "requires": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "requires": { + "xtend": "~4.0.0" + } + } + } + }, "merkle-patricia-tree": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", @@ -10216,6 +9819,18 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -10271,34 +9886,6 @@ "ethereum-cryptography": "^0.1.3", "ethjs-util": "0.1.6", "rlp": "^2.2.3" - }, - "dependencies": { - "keccak": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", - "integrity": "sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==", - "requires": { - "bindings": "^1.5.0", - "inherits": "^2.0.4", - "nan": "^2.14.0", - "safe-buffer": "^5.2.0" - } - }, - "secp256k1": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz", - "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", - "requires": { - "bindings": "^1.5.0", - "bip66": "^1.1.5", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "drbg.js": "^1.0.1", - "elliptic": "^6.5.2", - "nan": "^2.14.0", - "safe-buffer": "^5.1.2" - } - } } }, "ethereumjs-vm": { @@ -10437,6 +10024,37 @@ "xtend": "~4.0.0" } }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "requires": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "requires": { + "xtend": "~4.0.0" + } + } + } + }, "merkle-patricia-tree": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", @@ -10482,6 +10100,18 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -10555,6 +10185,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, "requires": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -10564,6 +10195,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, "requires": { "debug": "^2.3.3", "define-property": "^0.2.5", @@ -10578,6 +10210,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -10585,28 +10218,98 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=" + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -10683,6 +10386,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, "requires": { "type": "^2.0.0" }, @@ -10690,38 +10394,32 @@ "type": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==" + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", + "dev": true } } }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, "requires": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } } }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, "requires": { "array-unique": "^0.3.2", "define-property": "^1.0.0", @@ -10737,6 +10435,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -10744,33 +10443,17 @@ "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { - "kind-of": "^6.0.0" + "is-extendable": "^0.1.0" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true } } }, @@ -10789,17 +10472,6 @@ "checkpoint-store": "^1.1.0" } }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -10812,14 +10484,6 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "requires": { - "pend": "~1.2.0" - } - }, "fetch-ponyfill": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz", @@ -10829,6 +10493,12 @@ "node-fetch": "~1.7.1" }, "dependencies": { + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", @@ -10841,34 +10511,6 @@ } } }, - "file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" - } - } - }, "finalhandler": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", @@ -10904,92 +10546,150 @@ } } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "find-yarn-workspace-root": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz", + "integrity": "sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==", + "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "fs-extra": "^4.0.3", + "micromatch": "^3.1.4" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } } }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" - }, "flow-stoplight": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz", "integrity": "sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s=", "dev": true }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -11002,15 +10702,8 @@ "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "requires": { - "for-in": "^1.0.1" - } + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true }, "forever-agent": { "version": "0.6.1", @@ -11040,6 +10733,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, "requires": { "map-cache": "^0.2.2" } @@ -11051,64 +10745,41 @@ "dev": true, "optional": true }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, "fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true }, "get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "optional": true, "requires": { "pump": "^3.0.0" } @@ -11116,7 +10787,8 @@ "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true }, "getpass": { "version": "0.1.7", @@ -11131,6 +10803,7 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -11140,90 +10813,6 @@ "path-is-absolute": "^1.0.0" } }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - } - }, "global": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", @@ -11232,42 +10821,14 @@ "requires": { "min-document": "^2.19.0", "process": "~0.5.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "requires": { - "sparkles": "^1.0.0" + }, + "dependencies": { + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", + "dev": true + } } }, "got": { @@ -11305,53 +10866,8 @@ "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" - }, - "gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - }, - "dependencies": { - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - } - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "requires": { - "glogg": "^1.0.0" - } + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true }, "har-schema": { "version": "2.0.0", @@ -11373,6 +10889,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -11384,8 +10901,22 @@ "dev": true, "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, "has-symbol-support-x": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", @@ -11396,7 +10927,8 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true }, "has-to-string-tag-x": { "version": "1.4.1", @@ -11412,6 +10944,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, "requires": { "get-value": "^2.0.6", "has-values": "^1.0.0", @@ -11422,15 +10955,43 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, "requires": { "is-number": "^3.0.0", "kind-of": "^4.0.0" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -11441,6 +11002,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, "requires": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -11451,6 +11013,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -11463,38 +11026,12 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, "requires": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, - "hdkey": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-1.1.2.tgz", - "integrity": "sha512-PTQ4VKu0oRnCrYfLp04iQZ7T2Cxz0UsEXYauk2j8eh6PJXCpbXuCFhOmtIFtbET0i3PMWmHN9J11gU8LEgUljQ==", - "requires": { - "bs58check": "^2.1.2", - "safe-buffer": "^5.1.1", - "secp256k1": "^3.0.1" - }, - "dependencies": { - "secp256k1": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz", - "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", - "requires": { - "bindings": "^1.5.0", - "bip66": "^1.1.5", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "drbg.js": "^1.0.1", - "elliptic": "^6.5.2", - "nan": "^2.14.0", - "safe-buffer": "^5.1.2" - } - } - } - }, "heap": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", @@ -11505,6 +11042,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, "requires": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -11521,19 +11059,6 @@ "os-tmpdir": "^1.0.1" } }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" - }, "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -11614,17 +11139,20 @@ "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true }, "immediate": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", + "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -11633,17 +11161,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "invariant": { "version": "2.2.4", @@ -11654,11 +11173,6 @@ "loose-envify": "^1.0.0" } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" - }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -11666,28 +11180,13 @@ "dev": true, "optional": true }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "dev": true, + "requires": { + "kind-of": "^6.0.0" } }, "is-arguments": { @@ -11696,78 +11195,56 @@ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", "dev": true }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "is-callable": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "dev": true, + "requires": { + "kind-of": "^6.0.0" } }, "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } }, "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, "requires": { "is-plain-object": "^2.0.4" } }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, "is-finite": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", @@ -11780,61 +11257,23 @@ "integrity": "sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw=", "dev": true }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, "is-function": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", "dev": true }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, "is-hex-prefixed": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", "dev": true }, - "is-natural-number": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", - "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=" - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true }, "is-object": { "version": "1.0.1", @@ -11854,6 +11293,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, "requires": { "isobject": "^3.0.1" } @@ -11862,18 +11302,11 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, "requires": { "has-symbols": "^1.0.1" } }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "requires": { - "is-unc-path": "^1.0.0" - } - }, "is-retry-allowed": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", @@ -11881,15 +11314,11 @@ "dev": true, "optional": true }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, "is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -11897,30 +11326,14 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=" + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true }, "isarray": { "version": "1.0.0", @@ -11931,12 +11344,14 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true }, "isstream": { "version": "0.1.2", @@ -11958,7 +11373,9 @@ "js-sha3": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true, + "optional": true }, "js-tokens": { "version": "4.0.0", @@ -11972,12 +11389,6 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -12035,27 +11446,17 @@ "jsonify": "~0.0.0" } }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" - }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, "requires": { "graceful-fs": "^4.1.6" } @@ -12078,11 +11479,6 @@ "verror": "1.10.0" } }, - "just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=" - }, "keccak": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", @@ -12106,73 +11502,16 @@ "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "requires": { - "readable-stream": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "requires": { - "invert-kv": "^1.0.0" - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "requires": { - "flush-write-stream": "^1.0.2" + "graceful-fs": "^4.1.11" } }, "level-codec": { @@ -12197,34 +11536,11 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz", "integrity": "sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig==", + "dev": true, "requires": { "inherits": "^2.0.1", + "readable-stream": "^2.0.5", "xtend": "^4.0.0" - }, - "dependencies": { - "level-errors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.1.2.tgz", - "integrity": "sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w==", - "requires": { - "errno": "~0.1.1" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } } }, "level-mem": { @@ -12246,12 +11562,6 @@ "xtend": "~4.0.0" } }, - "immediate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", - "dev": true - }, "ltgt": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", @@ -12315,61 +11625,6 @@ "pull-stream": "^3.6.8", "typewiselite": "~1.0.0", "xtend": "~4.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "level-iterator-stream": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz", - "integrity": "sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.5", - "xtend": "^4.0.0" - } - }, - "ltgt": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.1.3.tgz", - "integrity": "sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "level-ws": { @@ -12381,51 +11636,6 @@ "inherits": "^2.0.3", "readable-stream": "^2.2.8", "xtend": "^4.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - } } }, "levelup": { @@ -12440,31 +11650,6 @@ "xtend": "~4.0.0" }, "dependencies": { - "abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "dev": true, - "requires": { - "xtend": "~4.0.0" - } - }, - "deferred-leveldown": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", - "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", - "dev": true, - "requires": { - "abstract-leveldown": "~5.0.0", - "inherits": "^2.0.3" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, "level-iterator-stream": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", @@ -12475,70 +11660,6 @@ "readable-stream": "^2.3.6", "xtend": "^4.0.0" } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, @@ -12585,78 +11706,26 @@ "integrity": "sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ=", "dev": true }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" - } - } - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "requires": { - "kind-of": "^6.0.2" - } - }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, "requires": { "object-visit": "^1.0.0" } }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "dependencies": { - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -12692,23 +11761,6 @@ "semaphore": ">=1.0.1" }, "dependencies": { - "abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "requires": { - "xtend": "~4.0.0" - } - }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, "ethereumjs-util": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", @@ -12724,55 +11776,6 @@ "safe-buffer": "^5.1.1" } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "level-codec": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", - "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==" - }, - "level-errors": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", - "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", - "requires": { - "errno": "~0.1.1" - } - }, - "levelup": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", - "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", - "requires": { - "level-codec": "~7.0.0", - "level-errors": "~1.0.3", - "prr": "~1.0.1", - "semver": "~5.4.1", - "xtend": "~4.0.0" - } - }, - "memdown": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", - "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", - "requires": { - "abstract-leveldown": "~2.7.1", - "functional-red-black-tree": "^1.0.1", - "immediate": "^3.2.3", - "inherits": "~2.0.1", - "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -12782,35 +11785,6 @@ "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } } } } @@ -12822,26 +11796,6 @@ "dev": true, "optional": true }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -12893,17 +11847,20 @@ "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true }, "minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -12914,17 +11871,6 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, "minizlib": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", @@ -12933,25 +11879,29 @@ "optional": true, "requires": { "minipass": "^2.9.0" + }, + "dependencies": { + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + } } }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } } }, "mkdirp": { @@ -12959,7 +11909,6 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, - "optional": true, "requires": { "minimist": "^1.2.5" } @@ -12987,15 +11936,51 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==" + "multibase": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", + "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", + "dev": true, + "optional": true, + "requires": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" + "multicodec": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", + "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", + "dev": true, + "optional": true, + "requires": { + "varint": "^5.0.0" + } + }, + "multihashes": { + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", + "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", + "dev": true, + "optional": true, + "requires": { + "buffer": "^5.5.0", + "multibase": "^0.7.0", + "varint": "^5.0.0" + }, + "dependencies": { + "multibase": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", + "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", + "dev": true, + "optional": true, + "requires": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + } + } }, "nano-json-stream-parser": { "version": "0.1.2", @@ -13008,6 +11993,7 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -13032,7 +12018,14 @@ "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true }, "node-addon-api": { "version": "2.0.2", @@ -13052,29 +12045,6 @@ "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", "dev": true }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, "normalize-url": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", @@ -13082,19 +12052,6 @@ "dev": true, "optional": true }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "requires": { - "once": "^1.3.2" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, "number-to-bn": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", @@ -13124,12 +12081,14 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true }, "object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, "requires": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", @@ -13139,12 +12098,60 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=" + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -13154,7 +12161,8 @@ "object-inspect": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true }, "object-is": { "version": "1.1.3", @@ -13198,6 +12206,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, "requires": { "isobject": "^3.0.0" } @@ -13206,6 +12215,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.18.0-next.0", @@ -13217,6 +12227,7 @@ "version": "1.18.0-next.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", @@ -13231,25 +12242,9 @@ "string.prototype.trimend": "^1.0.1", "string.prototype.trimstart": "^1.0.1" } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" } } }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, "object.getownpropertydescriptors": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", @@ -13260,32 +12255,15 @@ "es-abstract": "^1.17.0-next.1" } }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, "requires": { "isobject": "^3.0.1" } }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, "oboe": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.4.tgz", @@ -13310,66 +12288,17 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "requires": { - "readable-stream": "^2.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "requires": { - "lcid": "^1.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -13383,13 +12312,6 @@ "dev": true, "optional": true }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "optional": true - }, "p-timeout": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", @@ -13398,6 +12320,15 @@ "optional": true, "requires": { "p-finally": "^1.0.0" + }, + "dependencies": { + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "optional": true + } } }, "parse-asn1": { @@ -13414,40 +12345,12 @@ "safe-buffer": "^5.1.1" } }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, "parse-headers": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==", "dev": true }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==" - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" - }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -13458,43 +12361,106 @@ "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "patch-package": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.2.2.tgz", + "integrity": "sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg==", + "dev": true, "requires": { - "pinkie-promise": "^2.0.0" + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "find-yarn-workspace-root": "^1.2.1", + "fs-extra": "^7.0.1", + "is-ci": "^2.0.0", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.0", + "rimraf": "^2.6.3", + "semver": "^5.6.0", + "slash": "^2.0.0", + "tmp": "^0.0.33" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true }, "path-to-regexp": { "version": "0.1.7", @@ -13503,27 +12469,11 @@ "dev": true, "optional": true }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, "pbkdf2": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, "requires": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -13532,34 +12482,17 @@ "sha.js": "^2.4.8" } }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" - } - }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true }, "precond": { "version": "0.2.3", @@ -13574,27 +12507,17 @@ "dev": true, "optional": true }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" - }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true - }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true }, "promise-to-callback": { "version": "1.0.0", @@ -13620,7 +12543,8 @@ "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true }, "pseudomap": { "version": "1.0.2", @@ -13711,32 +12635,13 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "optional": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -13746,7 +12651,8 @@ "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true }, "query-string": { "version": "5.1.1", @@ -13800,25 +12706,6 @@ "unpipe": "1.0.0" } }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -13842,58 +12729,6 @@ } } }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "requires": { - "resolve": "^1.1.6" - } - }, "regenerate": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", @@ -13921,6 +12756,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" @@ -13960,41 +12796,27 @@ "dev": true, "requires": { "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } } }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true }, "repeating": { "version": "2.0.1", @@ -14005,21 +12827,6 @@ "is-finite": "^1.0.0" } }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==" - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -14046,55 +12853,22 @@ "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - } } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" - }, "resolve": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, "requires": { "path-parse": "^1.0.6" } }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "requires": { - "value-or-function": "^3.0.0" - } - }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true }, "responselike": { "version": "1.0.2", @@ -14118,7 +12892,8 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true }, "rimraf": { "version": "2.6.3", @@ -14133,6 +12908,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -14156,7 +12932,8 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true }, "safe-event-emitter": { "version": "1.0.1", @@ -14171,6 +12948,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, "requires": { "ret": "~0.1.10" } @@ -14187,18 +12965,12 @@ "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", "dev": true }, - "scrypt.js": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.3.0.tgz", - "integrity": "sha512-42LTc1nyFsyv/o0gcHtDztrn+aqpkaCNt5Qh7ATBZfhEZU7IC/0oT/qbBH+uRNoAPvs2fwiOId68FDEoSRA8/A==", - "requires": { - "scryptsy": "^1.2.1" - } - }, "scryptsy": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", + "dev": true, + "optional": true, "requires": { "pbkdf2": "^3.0.3" } @@ -14220,34 +12992,12 @@ "integrity": "sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg==", "dev": true }, - "seek-bzip": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", - "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", - "requires": { - "commander": "^2.8.1" - } - }, "semaphore": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", "dev": true }, - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "requires": { - "sver-compat": "^1.5.0" - } - }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -14325,11 +13075,6 @@ "xhr": "^2.3.3" } }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, "set-immediate-shim": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", @@ -14340,8 +13085,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, "requires": { "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", "is-plain-object": "^2.0.3", "split-string": "^3.0.1" }, @@ -14349,7 +13096,17 @@ "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true } } }, @@ -14370,6 +13127,7 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -14394,16 +13152,11 @@ "simple-concat": "^1.0.0" } }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, "requires": { "base": "^0.11.1", "debug": "^2.2.0", @@ -14419,6 +13172,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -14426,22 +13180,95 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=" + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -14449,6 +13276,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, "requires": { "define-property": "^1.0.0", "isobject": "^3.0.0", @@ -14459,35 +13287,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "^1.0.0" } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } } } }, @@ -14495,14 +13298,22 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, "requires": { "kind-of": "^3.2.0" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -14512,12 +13323,14 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true }, "source-map-resolve": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, "requires": { "atob": "^2.1.2", "decode-uri-component": "^0.2.0", @@ -14547,45 +13360,14 @@ "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==" - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, "requires": { "extend-shallow": "^3.0.0" } @@ -14615,15 +13397,11 @@ } } }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, "requires": { "define-property": "^0.2.5", "object-copy": "^0.1.0" @@ -14632,7 +13410,74 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=" + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true } } }, @@ -14643,16 +13488,6 @@ "dev": true, "optional": true }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==" - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" - }, "stream-to-pull-stream": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz", @@ -14678,16 +13513,6 @@ "dev": true, "optional": true }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, "string.prototype.trim": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.2.tgz", @@ -14724,6 +13549,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -14733,6 +13559,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -14742,6 +13569,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, "requires": { "safe-buffer": "~5.1.0" }, @@ -14749,34 +13577,11 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", - "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", - "requires": { - "is-natural-number": "^4.0.1" - } - }, "strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -14790,19 +13595,11 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, "swarm-js": { "version": "0.1.40", "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.40.tgz", @@ -14865,6 +13662,13 @@ "url-to-options": "^1.0.1" } }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "optional": true + }, "p-cancelable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", @@ -14961,62 +13765,25 @@ "yallist": "^3.0.3" }, "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, "optional": true, "requires": { - "minimist": "^1.2.5" - } - } - } - }, - "tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "minipass": "^2.6.0" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "optional": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" } } } @@ -15024,65 +13791,19 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, "requires": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" - }, "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", @@ -15099,38 +13820,26 @@ "rimraf": "^2.6.3" } }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, "requires": { "kind-of": "^3.0.2" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -15148,6 +13857,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, "requires": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", @@ -15155,23 +13865,6 @@ "safe-regex": "^1.1.0" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "requires": { - "through2": "^2.0.3" - } - }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", @@ -15219,7 +13912,8 @@ "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true }, "type-is": { "version": "1.6.18", @@ -15235,12 +13929,14 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, "requires": { "is-typedarray": "^1.0.0" } @@ -15273,20 +13969,6 @@ "dev": true, "optional": true }, - "unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "requires": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" - }, "underscore": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", @@ -15294,50 +13976,31 @@ "dev": true, "optional": true }, - "undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=" - }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", + "is-extendable": "^0.1.1", "set-value": "^2.0.1" - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" + }, + "dependencies": { + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + } } }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true }, "unorm": { "version": "1.6.0", @@ -15356,6 +14019,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, "requires": { "has-value": "^0.3.1", "isobject": "^3.0.0" @@ -15365,6 +14029,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, "requires": { "get-value": "^2.0.3", "has-values": "^0.1.4", @@ -15375,6 +14040,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, "requires": { "isarray": "1.0.0" } @@ -15384,20 +14050,11 @@ "has-values": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true } } }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" - }, "uri-js": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", @@ -15410,7 +14067,8 @@ "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true }, "url-parse-lax": { "version": "3.0.0", @@ -15439,7 +14097,25 @@ "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "utf-8-validate": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz", + "integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==", + "dev": true, + "requires": { + "node-gyp-build": "~3.7.0" + }, + "dependencies": { + "node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "dev": true + } + } }, "utf8": { "version": "3.0.0", @@ -15451,7 +14127,8 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true }, "util.promisify": { "version": "1.0.1", @@ -15478,27 +14155,12 @@ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=" + "varint": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", + "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", + "dev": true, + "optional": true }, "vary": { "version": "1.1.2", @@ -15518,101 +14180,6 @@ "extsprintf": "^1.2.0" } }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, "web3": { "version": "1.2.11", "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.11.tgz", @@ -15627,13 +14194,6 @@ "web3-net": "1.2.11", "web3-shh": "1.2.11", "web3-utils": "1.2.11" - }, - "dependencies": { - "@types/node": { - "version": "12.12.53", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.53.tgz", - "integrity": "sha512-51MYTDTyCziHb70wtGNFRwB4l+5JNvdqzFSkbDvpbftEgVUBEE+T5f7pROhWMp/fxp07oNIEQZd5bbfAH22ohQ==" - } } }, "web3-bzz": { @@ -15778,75 +14338,6 @@ "@ethersproject/abi": "5.0.0-beta.153", "underscore": "1.9.1", "web3-utils": "1.2.11" - }, - "dependencies": { - "@types/node": { - "version": "10.17.28", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.28.tgz", - "integrity": "sha512-dzjES1Egb4c1a89C7lKwQh8pwjYmlOAG9dW1pBgxEk57tMrLnssOfEthz8kdkNaBd7lIqQx7APm5+mZ619IiCQ==" - }, - "aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" - }, - "elliptic": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", - "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" - } - }, - "ethers": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", - "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", - "requires": { - "@types/node": "^10.3.2", - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "elliptic": "6.3.3", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.3", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" - }, - "scrypt-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", - "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=" - }, - "setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" - }, - "uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" - } } }, "web3-eth-accounts": { @@ -15935,15 +14426,6 @@ "requires": { "bn.js": "^4.11.9", "web3-utils": "1.2.11" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true, - "optional": true - } } }, "web3-eth-personal": { @@ -16038,12 +14520,6 @@ "ethereumjs-util": "^5.1.1" } }, - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true - }, "ethereumjs-abi": { "version": "git+https://git@github.com/ethereumjs/ethereumjs-abi.git#1ce6a1d64235fabe2aaf827fd606def55693508f", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", @@ -16092,6 +14568,14 @@ "ethereumjs-tx": "^1.2.2", "ethereumjs-util": "^5.0.0", "merkle-patricia-tree": "^2.1.2" + }, + "dependencies": { + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", + "dev": true + } } }, "ethereumjs-tx": { @@ -16102,14 +14586,6 @@ "requires": { "ethereum-common": "^0.0.18", "ethereumjs-util": "^5.0.0" - }, - "dependencies": { - "ethereum-common": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=", - "dev": true - } } }, "ethereumjs-util": { @@ -16298,6 +14774,37 @@ "xtend": "~4.0.0" } }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "requires": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "requires": { + "xtend": "~4.0.0" + } + } + } + }, "merkle-patricia-tree": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", @@ -16328,56 +14835,23 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } + "dev": true }, "ws": { "version": "5.2.2", @@ -16456,13 +14930,6 @@ "utf8": "3.0.0" }, "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true, - "optional": true - }, "eth-lib": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", @@ -16514,32 +14981,11 @@ "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==", "dev": true }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "ws": { "version": "3.3.3", @@ -16610,69 +15056,23 @@ "cookiejar": "^2.1.1" } }, - "xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true }, "yaeti": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", + "dev": true }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true - }, - "yargs": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", - "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "5.0.0-security.0" - } - }, - "yargs-parser": { - "version": "5.0.0-security.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", - "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } } } }, @@ -17068,7 +15468,8 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, "has-symbol-support-x": { "version": "1.4.2", @@ -17634,7 +16035,8 @@ "is-negative-zero": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=" + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true }, "is-number": { "version": "7.0.0", @@ -18945,52 +17347,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "multibase": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", - "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", - "dev": true, - "optional": true, - "requires": { - "base-x": "^3.0.8", - "buffer": "^5.5.0" - } - }, - "multicodec": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", - "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", - "dev": true, - "optional": true, - "requires": { - "varint": "^5.0.0" - } - }, - "multihashes": { - "version": "0.4.21", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", - "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", - "dev": true, - "optional": true, - "requires": { - "buffer": "^5.5.0", - "multibase": "^0.7.0", - "varint": "^5.0.0" - }, - "dependencies": { - "multibase": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", - "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", - "dev": true, - "optional": true, - "requires": { - "base-x": "^3.0.8", - "buffer": "^5.5.0" - } - } - } - }, "multimatch": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", @@ -22120,15 +20476,6 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, - "utf-8-validate": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.3.tgz", - "integrity": "sha512-jtJM6fpGv8C1SoH4PtG22pGto6x+Y8uPprW0tw3//gGFhDDTiuksgradgFN6yRayDP4SyZZa6ZMGHLIa17+M8A==", - "dev": true, - "requires": { - "node-gyp-build": "^4.2.0" - } - }, "utf8": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", @@ -22175,13 +20522,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 4fefea1b..5d42cf94 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "aave:fork:main": "npm run compile && MAINNET_FORK=true hardhat aave:mainnet", "aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify", "aave:main:full:initialize": "npm run compile && MAINNET_FORK=true full:initialize-tokens --pool Aave", + "prettier:lint": "npx prettier -c 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test/**/*.ts'", "dev:prettier": "prettier --write .", "ci:test": "npm run compile && npm run test", "ci:clean": "rm -rf ./artifacts ./cache ./types", @@ -113,7 +114,7 @@ }, "husky": { "hooks": { - "pre-commit": "pretty-quick --staged" + "pre-commit": "pretty-quick --pattern 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test/**/*.ts'" } }, "author": "Aave", diff --git a/tasks/dev/1_mock_tokens.ts b/tasks/dev/1_mock_tokens.ts index 550135f5..cc4713c5 100644 --- a/tasks/dev/1_mock_tokens.ts +++ b/tasks/dev/1_mock_tokens.ts @@ -1,9 +1,9 @@ -import {task} from 'hardhat/config'; -import {deployAllMockTokens} from '../../helpers/contracts-deployments'; +import { task } from 'hardhat/config'; +import { deployAllMockTokens } from '../../helpers/contracts-deployments'; task('dev:deploy-mock-tokens', 'Deploy mock tokens for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({verify}, localBRE) => { + .setAction(async ({ verify }, localBRE) => { await localBRE.run('set-DRE'); await deployAllMockTokens(verify); }); diff --git a/tasks/dev/3_lending_pool.ts b/tasks/dev/3_lending_pool.ts index b1aeb58c..9936abfa 100644 --- a/tasks/dev/3_lending_pool.ts +++ b/tasks/dev/3_lending_pool.ts @@ -1,22 +1,22 @@ -import {task} from 'hardhat/config'; +import { task } from 'hardhat/config'; import { deployATokensAndRatesHelper, deployLendingPool, deployLendingPoolConfigurator, deployStableAndVariableTokensHelper, } from '../../helpers/contracts-deployments'; -import {eContractid} from '../../helpers/types'; -import {waitForTx} from '../../helpers/misc-utils'; +import { eContractid } from '../../helpers/types'; +import { waitForTx } from '../../helpers/misc-utils'; import { getLendingPoolAddressesProvider, getLendingPool, getLendingPoolConfiguratorProxy, } from '../../helpers/contracts-getters'; -import {insertContractAddressInDb} from '../../helpers/contracts-helpers'; +import { insertContractAddressInDb } from '../../helpers/contracts-helpers'; task('dev:deploy-lending-pool', 'Deploy lending pool for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({verify}, localBRE) => { + .setAction(async ({ verify }, localBRE) => { await localBRE.run('set-DRE'); const addressesProvider = await getLendingPoolAddressesProvider(); diff --git a/tasks/dev/4_oracles.ts b/tasks/dev/4_oracles.ts index 97f14c8a..dbb6e708 100644 --- a/tasks/dev/4_oracles.ts +++ b/tasks/dev/4_oracles.ts @@ -1,4 +1,4 @@ -import {task} from 'hardhat/config'; +import { task } from 'hardhat/config'; import { deployPriceOracle, deployAaveOracle, @@ -10,10 +10,10 @@ import { deployAllMockAggregators, setInitialMarketRatesInRatesOracleByHelper, } from '../../helpers/oracles-helpers'; -import {ICommonConfiguration, iAssetBase, TokenContractId} from '../../helpers/types'; -import {waitForTx} from '../../helpers/misc-utils'; -import {getAllAggregatorsAddresses, getAllTokenAddresses} from '../../helpers/mock-helpers'; -import {ConfigNames, loadPoolConfig, getWethAddress} from '../../helpers/configuration'; +import { ICommonConfiguration, iAssetBase, TokenContractId } from '../../helpers/types'; +import { waitForTx } from '../../helpers/misc-utils'; +import { getAllAggregatorsAddresses, getAllTokenAddresses } from '../../helpers/mock-helpers'; +import { ConfigNames, loadPoolConfig, getWethAddress } from '../../helpers/configuration'; import { getAllMockedTokens, getLendingPoolAddressesProvider, @@ -23,12 +23,12 @@ import { task('dev:deploy-oracles', 'Deploy oracles for dev enviroment') .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); const { - Mocks: {AllAssetsInitialPrices}, - ProtocolGlobalParams: {UsdAddress, MockUsdPriceInWei}, + Mocks: { AllAssetsInitialPrices }, + ProtocolGlobalParams: { UsdAddress, MockUsdPriceInWei }, LendingRateOracleRatesCommon, } = poolConfig as ICommonConfiguration; @@ -67,7 +67,7 @@ task('dev:deploy-oracles', 'Deploy oracles for dev enviroment') const lendingRateOracle = await deployLendingRateOracle(verify); await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); - const {USD, ...tokensAddressesWithoutUsd} = allTokenAddresses; + const { USD, ...tokensAddressesWithoutUsd } = allTokenAddresses; const allReservesAddresses = { ...tokensAddressesWithoutUsd, }; diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index c62f31ce..37744343 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -16,10 +16,7 @@ import { import { tEthereumAddress, AavePools, eContractid } from '../../helpers/types'; import { waitForTx, filterMapBy } from '../../helpers/misc-utils'; -import { - configureReservesByHelper, - initReservesByHelper, -} from '../../helpers/init-helpers'; +import { configureReservesByHelper, initReservesByHelper } from '../../helpers/init-helpers'; import { getAllTokenAddresses } from '../../helpers/mock-helpers'; import { ZERO_ADDRESS } from '../../helpers/constants'; import { @@ -60,12 +57,7 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') ZERO_ADDRESS, verify ); - await configureReservesByHelper( - reservesParams, - protoPoolReservesAddresses, - testHelpers, - admin - ); + await configureReservesByHelper(reservesParams, protoPoolReservesAddresses, testHelpers, admin); const collateralManager = await deployLendingPoolCollateralManager(verify); await waitForTx( diff --git a/tasks/full/2_lending_pool.ts b/tasks/full/2_lending_pool.ts index 342d5365..f9898ec5 100644 --- a/tasks/full/2_lending_pool.ts +++ b/tasks/full/2_lending_pool.ts @@ -1,4 +1,4 @@ -import {task} from 'hardhat/config'; +import { task } from 'hardhat/config'; import { getEthersSignersAddresses, insertContractAddressInDb, @@ -9,8 +9,8 @@ import { deployLendingPoolConfigurator, deployStableAndVariableTokensHelper, } from '../../helpers/contracts-deployments'; -import {eContractid} from '../../helpers/types'; -import {waitForTx} from '../../helpers/misc-utils'; +import { eContractid } from '../../helpers/types'; +import { waitForTx } from '../../helpers/misc-utils'; import { getLendingPoolAddressesProvider, getLendingPool, @@ -19,7 +19,7 @@ import { task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({verify}, DRE) => { + .setAction(async ({ verify }, DRE) => { try { await DRE.run('set-DRE'); diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 444f55d8..af5484d9 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -6,13 +6,15 @@ import { deployAaveProtocolDataProvider, deployWETHGateway, } from '../../helpers/contracts-deployments'; -import { loadPoolConfig, ConfigNames, getWethAddress, getTreasuryAddress } from '../../helpers/configuration'; +import { + loadPoolConfig, + ConfigNames, + getWethAddress, + getTreasuryAddress, +} from '../../helpers/configuration'; import { eEthereumNetwork, ICommonConfiguration } from '../../helpers/types'; import { waitForTx } from '../../helpers/misc-utils'; -import { - initReservesByHelper, - configureReservesByHelper, -} from '../../helpers/init-helpers'; +import { initReservesByHelper, configureReservesByHelper } from '../../helpers/init-helpers'; import { exit } from 'process'; import { getAaveProtocolDataProvider, @@ -43,7 +45,14 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const treasuryAddress = await getTreasuryAddress(poolConfig); - await initReservesByHelper(ReservesConfig, reserveAssets, admin, treasuryAddress, ZERO_ADDRESS, verify); + await initReservesByHelper( + ReservesConfig, + reserveAssets, + admin, + treasuryAddress, + ZERO_ADDRESS, + verify + ); await configureReservesByHelper(ReservesConfig, reserveAssets, testHelpers, admin); const collateralManager = await deployLendingPoolCollateralManager(verify); diff --git a/tasks/migrations/aave.dev.ts b/tasks/migrations/aave.dev.ts index 1892cb53..842d1861 100644 --- a/tasks/migrations/aave.dev.ts +++ b/tasks/migrations/aave.dev.ts @@ -1,11 +1,11 @@ -import {task} from 'hardhat/config'; -import {checkVerification} from '../../helpers/etherscan-verification'; -import {ConfigNames} from '../../helpers/configuration'; -import {printContracts} from '../../helpers/misc-utils'; +import { task } from 'hardhat/config'; +import { checkVerification } from '../../helpers/etherscan-verification'; +import { ConfigNames } from '../../helpers/configuration'; +import { printContracts } from '../../helpers/misc-utils'; task('aave:dev', 'Deploy development enviroment') .addOptionalParam('verify', 'Verify contracts at Etherscan') - .setAction(async ({verify}, localBRE) => { + .setAction(async ({ verify }, localBRE) => { const POOL_NAME = ConfigNames.Aave; await localBRE.run('set-DRE'); @@ -18,19 +18,19 @@ task('aave:dev', 'Deploy development enviroment') console.log('Migration started\n'); console.log('1. Deploy mock tokens'); - await localBRE.run('dev:deploy-mock-tokens', {verify}); + await localBRE.run('dev:deploy-mock-tokens', { verify }); console.log('2. Deploy address provider'); - await localBRE.run('dev:deploy-address-provider', {verify}); + await localBRE.run('dev:deploy-address-provider', { verify }); console.log('3. Deploy lending pool'); - await localBRE.run('dev:deploy-lending-pool', {verify}); + await localBRE.run('dev:deploy-lending-pool', { verify }); console.log('4. Deploy oracles'); - await localBRE.run('dev:deploy-oracles', {verify, pool: POOL_NAME}); + await localBRE.run('dev:deploy-oracles', { verify, pool: POOL_NAME }); console.log('5. Initialize lending pool'); - await localBRE.run('dev:initialize-lending-pool', {verify, pool: POOL_NAME}); + await localBRE.run('dev:initialize-lending-pool', { verify, pool: POOL_NAME }); console.log('\nFinished migration'); printContracts(); diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index c8ae5430..76c32578 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -1,13 +1,13 @@ -import {task} from 'hardhat/config'; -import {ExternalProvider} from '@ethersproject/providers'; -import {checkVerification} from '../../helpers/etherscan-verification'; -import {ConfigNames} from '../../helpers/configuration'; -import {EthereumNetworkNames} from '../../helpers/types'; -import {printContracts} from '../../helpers/misc-utils'; +import { task } from 'hardhat/config'; +import { ExternalProvider } from '@ethersproject/providers'; +import { checkVerification } from '../../helpers/etherscan-verification'; +import { ConfigNames } from '../../helpers/configuration'; +import { EthereumNetworkNames } from '../../helpers/types'; +import { printContracts } from '../../helpers/misc-utils'; task('aave:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({verify}, DRE) => { + .setAction(async ({ verify }, DRE) => { const POOL_NAME = ConfigNames.Aave; const network = DRE.network.name; await DRE.run('set-DRE'); @@ -27,27 +27,27 @@ task('aave:mainnet', 'Deploy development enviroment') console.log('Migration started\n'); console.log('1. Deploy address provider'); - await DRE.run('full:deploy-address-provider', {pool: POOL_NAME}); + await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); console.log('2. Deploy lending pool'); await DRE.run('full:deploy-lending-pool'); console.log('3. Deploy oracles'); - await DRE.run('full:deploy-oracles', {pool: POOL_NAME}); + await DRE.run('full:deploy-oracles', { pool: POOL_NAME }); console.log('4. Deploy Data Provider'); - await DRE.run('full:data-provider', {pool: POOL_NAME}); + await DRE.run('full:data-provider', { pool: POOL_NAME }); console.log('5. Initialize lending pool'); - await DRE.run('full:initialize-lending-pool', {pool: POOL_NAME}); + await DRE.run('full:initialize-lending-pool', { pool: POOL_NAME }); if (verify) { printContracts(); console.log('4. Veryfing contracts'); - await DRE.run('verify:general', {all: true, pool: POOL_NAME}); + await DRE.run('verify:general', { all: true, pool: POOL_NAME }); console.log('5. Veryfing aTokens and debtTokens'); - await DRE.run('verify:tokens', {pool: POOL_NAME}); + await DRE.run('verify:tokens', { pool: POOL_NAME }); } if (network.includes('tenderly')) { diff --git a/tasks/misc/print-contracts.ts b/tasks/misc/print-contracts.ts index d3caf0cc..a9e8b986 100644 --- a/tasks/misc/print-contracts.ts +++ b/tasks/misc/print-contracts.ts @@ -1,5 +1,5 @@ -import {task} from 'hardhat/config'; -import {printContracts} from '../../helpers/misc-utils'; +import { task } from 'hardhat/config'; +import { printContracts } from '../../helpers/misc-utils'; task('print-contracts', 'Inits the DRE, to have access to all the plugins').setAction( async ({}, localBRE) => { diff --git a/tasks/misc/verify-sc.ts b/tasks/misc/verify-sc.ts index 81f0970c..12484d47 100644 --- a/tasks/misc/verify-sc.ts +++ b/tasks/misc/verify-sc.ts @@ -1,5 +1,5 @@ -import {task} from 'hardhat/config'; -import {verifyContract, checkVerification} from '../../helpers/etherscan-verification'; +import { task } from 'hardhat/config'; +import { verifyContract, checkVerification } from '../../helpers/etherscan-verification'; interface VerifyParams { contractName: string; @@ -19,7 +19,7 @@ task('verify-sc', 'Inits the DRE, to have access to all the plugins') 'arguments for contract constructor', [] ) - .setAction(async ({address, constructorArguments = [], libraries}: VerifyParams, localBRE) => { + .setAction(async ({ address, constructorArguments = [], libraries }: VerifyParams, localBRE) => { await localBRE.run('set-DRE'); checkVerification(); diff --git a/test/addresses-provider-registry.spec.ts b/test/addresses-provider-registry.spec.ts index d26eae21..5ded1413 100644 --- a/test/addresses-provider-registry.spec.ts +++ b/test/addresses-provider-registry.spec.ts @@ -1,12 +1,12 @@ -import {TestEnv, makeSuite} from './helpers/make-suite'; -import {ZERO_ADDRESS} from '../helpers/constants'; -import {ProtocolErrors} from '../helpers/types'; +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { ZERO_ADDRESS } from '../helpers/constants'; +import { ProtocolErrors } from '../helpers/types'; -const {expect} = require('chai'); +const { expect } = require('chai'); makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => { it('Checks the addresses provider is added to the registry', async () => { - const {addressesProvider, registry} = testEnv; + const { addressesProvider, registry } = testEnv; const providers = await registry.getAddressesProvidersList(); @@ -18,8 +18,8 @@ makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => { }); it('tries to register an addresses provider with id 0', async () => { - const {users, registry} = testEnv; - const {LPAPR_INVALID_ADDRESSES_PROVIDER_ID} = ProtocolErrors; + const { users, registry } = testEnv; + const { LPAPR_INVALID_ADDRESSES_PROVIDER_ID } = ProtocolErrors; await expect(registry.registerAddressesProvider(users[2].address, '0')).to.be.revertedWith( LPAPR_INVALID_ADDRESSES_PROVIDER_ID @@ -27,7 +27,7 @@ makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => { }); it('Registers a new mock addresses provider', async () => { - const {users, registry} = testEnv; + const { users, registry } = testEnv; //simulating an addresses provider using the users[1] wallet address await registry.registerAddressesProvider(users[1].address, '2'); @@ -42,7 +42,7 @@ makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => { }); it('Removes the mock addresses provider', async () => { - const {users, registry, addressesProvider} = testEnv; + const { users, registry, addressesProvider } = testEnv; const id = await registry.getAddressesProviderIdByAddress(users[1].address); @@ -61,9 +61,9 @@ makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => { }); it('Tries to remove a unregistered addressesProvider', async () => { - const {LPAPR_PROVIDER_NOT_REGISTERED} = ProtocolErrors; + const { LPAPR_PROVIDER_NOT_REGISTERED } = ProtocolErrors; - const {users, registry} = testEnv; + const { users, registry } = testEnv; await expect(registry.unregisterAddressesProvider(users[2].address)).to.be.revertedWith( LPAPR_PROVIDER_NOT_REGISTERED @@ -71,9 +71,9 @@ makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => { }); it('Tries to remove a unregistered addressesProvider', async () => { - const {LPAPR_PROVIDER_NOT_REGISTERED} = ProtocolErrors; + const { LPAPR_PROVIDER_NOT_REGISTERED } = ProtocolErrors; - const {users, registry} = testEnv; + const { users, registry } = testEnv; await expect(registry.unregisterAddressesProvider(users[2].address)).to.be.revertedWith( LPAPR_PROVIDER_NOT_REGISTERED @@ -81,7 +81,7 @@ makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => { }); it('Tries to add an already added addressesProvider with a different id. Should overwrite the previous id', async () => { - const {users, registry, addressesProvider} = testEnv; + const { users, registry, addressesProvider } = testEnv; await registry.registerAddressesProvider(addressesProvider.address, '2'); diff --git a/test/atoken-modifiers.spec.ts b/test/atoken-modifiers.spec.ts index 4649dc21..d379210c 100644 --- a/test/atoken-modifiers.spec.ts +++ b/test/atoken-modifiers.spec.ts @@ -1,33 +1,33 @@ -import {expect} from 'chai'; -import {makeSuite, TestEnv} from './helpers/make-suite'; -import {ProtocolErrors} from '../helpers/types'; +import { expect } from 'chai'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors } from '../helpers/types'; makeSuite('AToken: Modifiers', (testEnv: TestEnv) => { - const {CT_CALLER_MUST_BE_LENDING_POOL} = ProtocolErrors; + const { CT_CALLER_MUST_BE_LENDING_POOL } = ProtocolErrors; it('Tries to invoke mint not being the LendingPool', async () => { - const {deployer, aDai} = testEnv; + const { deployer, aDai } = testEnv; await expect(aDai.mint(deployer.address, '1', '1')).to.be.revertedWith( CT_CALLER_MUST_BE_LENDING_POOL ); }); it('Tries to invoke burn not being the LendingPool', async () => { - const {deployer, aDai} = testEnv; + const { deployer, aDai } = testEnv; await expect(aDai.burn(deployer.address, deployer.address, '1', '1')).to.be.revertedWith( CT_CALLER_MUST_BE_LENDING_POOL ); }); it('Tries to invoke transferOnLiquidation not being the LendingPool', async () => { - const {deployer, users, aDai} = testEnv; + const { deployer, users, aDai } = testEnv; await expect( aDai.transferOnLiquidation(deployer.address, users[0].address, '1') ).to.be.revertedWith(CT_CALLER_MUST_BE_LENDING_POOL); }); it('Tries to invoke transferUnderlyingTo not being the LendingPool', async () => { - const {deployer, aDai} = testEnv; + const { deployer, aDai } = testEnv; await expect(aDai.transferUnderlyingTo(deployer.address, '1')).to.be.revertedWith( CT_CALLER_MUST_BE_LENDING_POOL ); diff --git a/test/atoken-transfer.spec.ts b/test/atoken-transfer.spec.ts index bba0da59..7414eea9 100644 --- a/test/atoken-transfer.spec.ts +++ b/test/atoken-transfer.spec.ts @@ -1,10 +1,10 @@ -import {APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, ZERO_ADDRESS} from '../helpers/constants'; -import {convertToCurrencyDecimals} from '../helpers/contracts-helpers'; -import {expect} from 'chai'; -import {ethers} from 'ethers'; -import {RateMode, ProtocolErrors} from '../helpers/types'; -import {makeSuite, TestEnv} from './helpers/make-suite'; -import {CommonsConfig} from '../markets/aave/commons'; +import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, ZERO_ADDRESS } from '../helpers/constants'; +import { convertToCurrencyDecimals } from '../helpers/contracts-helpers'; +import { expect } from 'chai'; +import { ethers } from 'ethers'; +import { RateMode, ProtocolErrors } from '../helpers/types'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { CommonsConfig } from '../markets/aave/commons'; const AAVE_REFERRAL = CommonsConfig.ProtocolGlobalParams.AaveReferral; @@ -16,7 +16,7 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { } = ProtocolErrors; it('User 0 deposits 1000 DAI, transfers to user 1', async () => { - const {users, pool, dai, aDai} = testEnv; + const { users, pool, dai, aDai } = testEnv; await dai.connect(users[0].signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); @@ -46,7 +46,7 @@ makeSuite('AToken: Transfer', (testEnv: 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 { users, pool, weth, helpersContract } = testEnv; const userAddress = await pool.signer.getAddress(); await weth.connect(users[0].signer).mint(await convertToCurrencyDecimals(weth.address, '1')); @@ -75,7 +75,7 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { }); 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 { users, pool, aDai, dai, weth } = testEnv; const aDAItoTransfer = await convertToCurrencyDecimals(dai.address, '1000'); @@ -86,7 +86,7 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { }); 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 { users, pool, aDai, dai, weth } = testEnv; const aDAItoTransfer = await convertToCurrencyDecimals(dai.address, '100'); diff --git a/test/configurator.spec.ts b/test/configurator.spec.ts index e92b70bd..1d888db0 100644 --- a/test/configurator.spec.ts +++ b/test/configurator.spec.ts @@ -1,10 +1,10 @@ -import {TestEnv, makeSuite} from './helpers/make-suite'; -import {APPROVAL_AMOUNT_LENDING_POOL, RAY} from '../helpers/constants'; -import {convertToCurrencyDecimals} from '../helpers/contracts-helpers'; -import {ProtocolErrors} from '../helpers/types'; +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { APPROVAL_AMOUNT_LENDING_POOL, RAY } from '../helpers/constants'; +import { convertToCurrencyDecimals } from '../helpers/contracts-helpers'; +import { ProtocolErrors } from '../helpers/types'; import { strategyWETH } from '../markets/aave/reservesConfigs'; -const {expect} = require('chai'); +const { expect } = require('chai'); makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { const { @@ -18,7 +18,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { } = ProtocolErrors; it('Reverts trying to set an invalid reserve factor', async () => { - const {configurator, weth} = testEnv; + const { configurator, weth } = testEnv; const invalidReserveFactor = 65536; @@ -28,22 +28,22 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Deactivates the ETH reserve', async () => { - const {configurator, weth, helpersContract} = testEnv; + const { configurator, weth, helpersContract } = testEnv; await configurator.deactivateReserve(weth.address); - const {isActive} = await helpersContract.getReserveConfigurationData(weth.address); + const { isActive } = await helpersContract.getReserveConfigurationData(weth.address); expect(isActive).to.be.equal(false); }); it('Rectivates the ETH reserve', async () => { - const {configurator, weth, helpersContract} = testEnv; + const { configurator, weth, helpersContract } = testEnv; await configurator.activateReserve(weth.address); - const {isActive} = await helpersContract.getReserveConfigurationData(weth.address); + const { isActive } = await helpersContract.getReserveConfigurationData(weth.address); expect(isActive).to.be.equal(true); }); it('Check the onlyAaveAdmin on deactivateReserve ', async () => { - const {configurator, users, weth} = testEnv; + const { configurator, users, weth } = testEnv; await expect( configurator.connect(users[2].signer).deactivateReserve(weth.address), CALLER_NOT_POOL_ADMIN @@ -51,7 +51,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Check the onlyAaveAdmin on activateReserve ', async () => { - const {configurator, users, weth} = testEnv; + const { configurator, users, weth } = testEnv; await expect( configurator.connect(users[2].signer).activateReserve(weth.address), CALLER_NOT_POOL_ADMIN @@ -59,9 +59,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Freezes the ETH reserve', async () => { - const {configurator, weth, helpersContract} = testEnv; - - + const { configurator, weth, helpersContract } = testEnv; await configurator.freezeReserve(weth.address); const { @@ -88,7 +86,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Unfreezes the ETH reserve', async () => { - const {configurator, helpersContract, weth} = testEnv; + const { configurator, helpersContract, weth } = testEnv; await configurator.unfreezeReserve(weth.address); const { @@ -115,7 +113,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Check the onlyAaveAdmin on freezeReserve ', async () => { - const {configurator, users, weth} = testEnv; + const { configurator, users, weth } = testEnv; await expect( configurator.connect(users[2].signer).freezeReserve(weth.address), CALLER_NOT_POOL_ADMIN @@ -123,7 +121,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Check the onlyAaveAdmin on unfreezeReserve ', async () => { - const {configurator, users, weth} = testEnv; + const { configurator, users, weth } = testEnv; await expect( configurator.connect(users[2].signer).unfreezeReserve(weth.address), CALLER_NOT_POOL_ADMIN @@ -131,7 +129,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Deactivates the ETH reserve for borrowing', async () => { - const {configurator, helpersContract, weth} = testEnv; + const { configurator, helpersContract, weth } = testEnv; await configurator.disableBorrowingOnReserve(weth.address); const { decimals, @@ -157,9 +155,9 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Activates the ETH reserve for borrowing', async () => { - const {configurator, weth, helpersContract} = testEnv; + const { configurator, weth, helpersContract } = testEnv; await configurator.enableBorrowingOnReserve(weth.address, true); - const {variableBorrowIndex} = await helpersContract.getReserveData(weth.address); + const { variableBorrowIndex } = await helpersContract.getReserveData(weth.address); const { decimals, @@ -187,7 +185,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Check the onlyAaveAdmin on disableBorrowingOnReserve ', async () => { - const {configurator, users, weth} = testEnv; + const { configurator, users, weth } = testEnv; await expect( configurator.connect(users[2].signer).disableBorrowingOnReserve(weth.address), CALLER_NOT_POOL_ADMIN @@ -195,7 +193,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => { - const {configurator, users, weth} = testEnv; + const { configurator, users, weth } = testEnv; await expect( configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, true), CALLER_NOT_POOL_ADMIN @@ -203,7 +201,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Deactivates the ETH reserve as collateral', async () => { - const {configurator, helpersContract, weth} = testEnv; + const { configurator, helpersContract, weth } = testEnv; await configurator.configureReserveAsCollateral(weth.address, 0, 0, 0); const { @@ -230,7 +228,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Activates the ETH reserve as collateral', async () => { - const {configurator, helpersContract, weth} = testEnv; + const { configurator, helpersContract, weth } = testEnv; await configurator.configureReserveAsCollateral(weth.address, '8000', '8250', '10500'); const { @@ -257,7 +255,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Check the onlyAaveAdmin on configureReserveAsCollateral ', async () => { - const {configurator, users, weth} = testEnv; + const { configurator, users, weth } = testEnv; await expect( configurator .connect(users[2].signer) @@ -267,7 +265,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Disable stable borrow rate on the ETH reserve', async () => { - const {configurator, helpersContract, weth} = testEnv; + const { configurator, helpersContract, weth } = testEnv; await configurator.disableReserveStableRate(weth.address); const { decimals, @@ -293,7 +291,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Enables stable borrow rate on the ETH reserve', async () => { - const {configurator, helpersContract, weth} = testEnv; + const { configurator, helpersContract, weth } = testEnv; await configurator.enableReserveStableRate(weth.address); const { decimals, @@ -319,7 +317,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Check the onlyAaveAdmin on disableReserveStableRate', async () => { - const {configurator, users, weth} = testEnv; + const { configurator, users, weth } = testEnv; await expect( configurator.connect(users[2].signer).disableReserveStableRate(weth.address), CALLER_NOT_POOL_ADMIN @@ -327,7 +325,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Check the onlyAaveAdmin on enableReserveStableRate', async () => { - const {configurator, users, weth} = testEnv; + const { configurator, users, weth } = testEnv; await expect( configurator.connect(users[2].signer).enableReserveStableRate(weth.address), CALLER_NOT_POOL_ADMIN @@ -335,7 +333,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Changes the reserve factor of WETH', async () => { - const {configurator, helpersContract, weth} = testEnv; + const { configurator, helpersContract, weth } = testEnv; await configurator.setReserveFactor(weth.address, '1000'); const { decimals, @@ -361,7 +359,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Check the onlyLendingPoolManager on setReserveFactor', async () => { - const {configurator, users, weth} = testEnv; + const { configurator, users, weth } = testEnv; await expect( configurator.connect(users[2].signer).setReserveFactor(weth.address, '2000'), CALLER_NOT_POOL_ADMIN @@ -369,7 +367,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { }); it('Reverts when trying to disable the DAI reserve with liquidity on it', async () => { - const {dai, pool, configurator} = testEnv; + const { dai, pool, configurator } = testEnv; const userAddress = await pool.signer.getAddress(); await dai.mint(await convertToCurrencyDecimals(dai.address, '1000')); diff --git a/test/flashloan.spec.ts b/test/flashloan.spec.ts index 7bfa2781..c6e5dcff 100644 --- a/test/flashloan.spec.ts +++ b/test/flashloan.spec.ts @@ -1,20 +1,20 @@ import BigNumber from 'bignumber.js'; -import {TestEnv, makeSuite} from './helpers/make-suite'; -import {APPROVAL_AMOUNT_LENDING_POOL, oneRay} from '../helpers/constants'; -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 { TestEnv, makeSuite } from './helpers/make-suite'; +import { APPROVAL_AMOUNT_LENDING_POOL, oneRay } from '../helpers/constants'; +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, getStableDebtToken, getVariableDebtToken, } from '../helpers/contracts-getters'; -const {expect} = require('chai'); +const { expect } = require('chai'); makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver; @@ -32,7 +32,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Deposits WETH into the reserve', async () => { - const {pool, weth} = testEnv; + const { pool, weth } = testEnv; const userAddress = await pool.signer.getAddress(); const amountToDeposit = ethers.utils.parseEther('1'); @@ -44,7 +44,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Takes WETH flashloan with mode = 0, returns the funds correctly', async () => { - const {pool, helpersContract, weth} = testEnv; + const { pool, helpersContract, weth } = testEnv; await pool.flashLoan( _mockFlashLoanReceiver.address, @@ -73,7 +73,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Takes an ETH flashloan with mode = 0 as big as the available liquidity', async () => { - const {pool, helpersContract, weth} = testEnv; + const { pool, helpersContract, weth } = testEnv; const reserveDataBefore = await helpersContract.getReserveData(weth.address); const txResult = await pool.flashLoan( @@ -101,7 +101,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Takes WETH flashloan, does not return the funds with mode = 0. (revert expected)', async () => { - const {pool, weth, users} = testEnv; + const { pool, weth, users } = testEnv; const caller = users[1]; await _mockFlashLoanReceiver.setFailExecutionTransfer(true); @@ -121,7 +121,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Takes WETH flashloan, simulating a receiver as EOA (revert expected)', async () => { - const {pool, weth, users} = testEnv; + const { pool, weth, users } = testEnv; const caller = users[1]; await _mockFlashLoanReceiver.setFailExecutionTransfer(true); await _mockFlashLoanReceiver.setSimulateEOA(true); @@ -142,7 +142,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Takes a WETH flashloan with an invalid mode. (revert expected)', async () => { - const {pool, weth, users} = testEnv; + const { pool, weth, users } = testEnv; const caller = users[1]; await _mockFlashLoanReceiver.setSimulateEOA(false); await _mockFlashLoanReceiver.setFailExecutionTransfer(true); @@ -163,7 +163,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Caller deposits 1000 DAI as collateral, Takes WETH flashloan with mode = 2, does not return the funds. A variable loan for caller is created', async () => { - const {dai, pool, weth, users, helpersContract} = testEnv; + const { dai, pool, weth, users, helpersContract } = testEnv; const caller = users[1]; @@ -188,7 +188,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { '0x10', '0' ); - const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address ); @@ -200,7 +200,7 @@ 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, users} = testEnv; + const { pool, weth, users } = testEnv; const caller = users[1]; await expect( @@ -218,7 +218,7 @@ 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, users} = testEnv; + const { pool, deployer, weth, users } = testEnv; const caller = users[1]; await expect( @@ -235,7 +235,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Deposits USDC into the reserve', async () => { - const {usdc, pool} = testEnv; + const { usdc, pool } = testEnv; const userAddress = await pool.signer.getAddress(); await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000')); @@ -248,7 +248,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Takes out a 500 USDC flashloan, returns the funds correctly', async () => { - const {usdc, pool, helpersContract, deployer: depositor} = testEnv; + const { usdc, pool, helpersContract, deployer: depositor } = testEnv; await _mockFlashLoanReceiver.setFailExecutionTransfer(false); @@ -268,7 +268,6 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { const reserveDataAfter = helpersContract.getReserveData(usdc.address); - const reserveData = await helpersContract.getReserveData(usdc.address); const userData = await helpersContract.getUserReserveData(usdc.address, depositor.address); @@ -292,7 +291,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Takes out a 500 USDC flashloan with mode = 0, does not return the funds. (revert expected)', async () => { - const {usdc, pool, users} = testEnv; + const { usdc, pool, users } = testEnv; const caller = users[2]; const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); @@ -315,7 +314,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Caller deposits 5 WETH as collateral, Takes a USDC flashloan with mode = 2, does not return the funds. A loan for caller is created', async () => { - const {usdc, pool, weth, users, helpersContract} = testEnv; + const { usdc, pool, weth, users, helpersContract } = testEnv; const caller = users[2]; @@ -342,7 +341,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { '0x10', '0' ); - const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( usdc.address ); @@ -354,7 +353,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Caller deposits 1000 DAI as collateral, Takes a WETH flashloan with mode = 0, does not approve the transfer of the funds', async () => { - const {dai, pool, weth, users} = testEnv; + const { dai, pool, weth, users } = testEnv; const caller = users[3]; await dai.connect(caller.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); @@ -386,7 +385,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Caller takes a WETH flashloan with mode = 1', async () => { - const {dai, pool, weth, users, helpersContract} = testEnv; + const { dai, pool, weth, users, helpersContract } = testEnv; const caller = users[3]; @@ -406,7 +405,9 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { '0' ); - const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address); + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); const wethDebtToken = await getStableDebtToken(stableDebtTokenAddress); @@ -416,7 +417,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('Caller takes a WETH flashloan with mode = 1 onBehalfOf user without allowance', async () => { - const {dai, pool, weth, users, helpersContract} = testEnv; + const { dai, pool, weth, users, helpersContract } = testEnv; const caller = users[5]; const onBehalfOf = users[4]; @@ -452,7 +453,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); 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 { dai, pool, weth, users, helpersContract } = testEnv; const caller = users[5]; const onBehalfOf = users[4]; @@ -480,7 +481,9 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { '0' ); - const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address); + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); const wethDebtToken = await getStableDebtToken(stableDebtTokenAddress); diff --git a/test/helpers/scenario-engine.ts b/test/helpers/scenario-engine.ts index bb4f82f8..92c686f4 100644 --- a/test/helpers/scenario-engine.ts +++ b/test/helpers/scenario-engine.ts @@ -1,4 +1,4 @@ -import {TestEnv, SignerWithAddress} from './make-suite'; +import { TestEnv, SignerWithAddress } from './make-suite'; import { mint, approve, @@ -11,7 +11,7 @@ import { rebalanceStableBorrowRate, delegateBorrowAllowance, } from './actions'; -import {RateMode} from '../../helpers/types'; +import { RateMode } from '../../helpers/types'; export interface Action { name: string; @@ -33,14 +33,14 @@ export interface Scenario { export const executeStory = async (story: Story, testEnv: TestEnv) => { for (const action of story.actions) { - const {users} = testEnv; + const { users } = testEnv; await executeAction(action, users, testEnv); } }; const executeAction = async (action: Action, users: SignerWithAddress[], testEnv: TestEnv) => { - const {reserve, user: userIndex, borrowRateMode} = action.args; - const {name, expected, revertMessage} = action; + const { reserve, user: userIndex, borrowRateMode } = action.args; + const { name, expected, revertMessage } = action; if (!name || name === '') { throw 'Action name is missing'; @@ -75,7 +75,7 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv switch (name) { case 'mint': - const {amount} = action.args; + const { amount } = action.args; if (!amount || amount === '') { throw `Invalid amount of ${reserve} to mint`; @@ -90,7 +90,7 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv case 'deposit': { - const {amount, sendValue, onBehalfOf: onBehalfOfIndex} = action.args; + const { amount, sendValue, onBehalfOf: onBehalfOfIndex } = action.args; const onBehalfOf = onBehalfOfIndex ? users[parseInt(onBehalfOfIndex)].address : user.address; @@ -114,7 +114,7 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv case 'delegateBorrowAllowance': { - const {amount, toUser: toUserIndex} = action.args; + const { amount, toUser: toUserIndex } = action.args; const toUser = users[parseInt(toUserIndex, 10)].address; if (!amount || amount === '') { throw `Invalid amount to deposit into the ${reserve} reserve`; @@ -135,7 +135,7 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv case 'withdraw': { - const {amount} = action.args; + const { amount } = action.args; if (!amount || amount === '') { throw `Invalid amount to withdraw from the ${reserve} reserve`; @@ -146,7 +146,7 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv break; case 'borrow': { - const {amount, timeTravel, onBehalfOf: onBehalfOfIndex} = action.args; + const { amount, timeTravel, onBehalfOf: onBehalfOfIndex } = action.args; const onBehalfOf = onBehalfOfIndex ? users[parseInt(onBehalfOfIndex)].address @@ -172,8 +172,8 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv case 'repay': { - const {amount, borrowRateMode, sendValue} = action.args; - let {onBehalfOf: onBehalfOfIndex} = action.args; + const { amount, borrowRateMode, sendValue } = action.args; + let { onBehalfOf: onBehalfOfIndex } = action.args; if (!amount || amount === '') { throw `Invalid amount to repay into the ${reserve} reserve`; @@ -205,7 +205,7 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv case 'setUseAsCollateral': { - const {useAsCollateral} = action.args; + const { useAsCollateral } = action.args; if (!useAsCollateral || useAsCollateral === '') { throw `A valid value for useAsCollateral needs to be set when calling setUseReserveAsCollateral on reserve ${reserve}`; @@ -220,7 +220,7 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv case 'rebalanceStableBorrowRate': { - const {target: targetIndex} = action.args; + const { target: targetIndex } = action.args; if (!targetIndex || targetIndex === '') { throw `A target must be selected when trying to rebalance a stable rate`; diff --git a/test/helpers/utils/calculations.ts b/test/helpers/utils/calculations.ts index 752207e6..5db28ec2 100644 --- a/test/helpers/utils/calculations.ts +++ b/test/helpers/utils/calculations.ts @@ -1211,7 +1211,6 @@ export const calcExpectedInterestRates = ( ): BigNumber[] => { const { reservesParams } = configuration; - const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol); const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[ reserveIndex diff --git a/test/helpers/utils/math.ts b/test/helpers/utils/math.ts index 66be629c..efd296e0 100644 --- a/test/helpers/utils/math.ts +++ b/test/helpers/utils/math.ts @@ -1,5 +1,13 @@ import BigNumber from 'bignumber.js'; -import {RAY, WAD, HALF_RAY, HALF_WAD, WAD_RAY_RATIO, HALF_PERCENTAGE, PERCENTAGE_FACTOR} from '../../../helpers/constants'; +import { + RAY, + WAD, + HALF_RAY, + HALF_WAD, + WAD_RAY_RATIO, + HALF_PERCENTAGE, + PERCENTAGE_FACTOR, +} from '../../../helpers/constants'; declare module 'bignumber.js' { interface BigNumber { @@ -68,19 +76,22 @@ BigNumber.prototype.wadToRay = function (): BigNumber { return this.multipliedBy(WAD_RAY_RATIO).decimalPlaces(0, BigNumber.ROUND_DOWN); }; - - - BigNumber.prototype.halfPercentage = (): BigNumber => { return new BigNumber(HALF_PERCENTAGE).decimalPlaces(0, BigNumber.ROUND_DOWN); }; BigNumber.prototype.percentMul = function (b: BigNumber): BigNumber { - return this.halfPercentage().plus(this.multipliedBy(b)).div(PERCENTAGE_FACTOR).decimalPlaces(0, BigNumber.ROUND_DOWN); + return this.halfPercentage() + .plus(this.multipliedBy(b)) + .div(PERCENTAGE_FACTOR) + .decimalPlaces(0, BigNumber.ROUND_DOWN); }; BigNumber.prototype.percentDiv = function (a: BigNumber): BigNumber { const halfA = a.div(2).decimalPlaces(0, BigNumber.ROUND_DOWN); - return halfA.plus(this.multipliedBy(PERCENTAGE_FACTOR)).div(a).decimalPlaces(0, BigNumber.ROUND_DOWN); -}; \ No newline at end of file + return halfA + .plus(this.multipliedBy(PERCENTAGE_FACTOR)) + .div(a) + .decimalPlaces(0, BigNumber.ROUND_DOWN); +}; diff --git a/test/lending-pool-addresses-provider.spec.ts b/test/lending-pool-addresses-provider.spec.ts index f87ccaf1..48570458 100644 --- a/test/lending-pool-addresses-provider.spec.ts +++ b/test/lending-pool-addresses-provider.spec.ts @@ -1,19 +1,19 @@ -import {expect} from 'chai'; -import {createRandomAddress} from '../helpers/misc-utils'; -import {makeSuite, TestEnv} from './helpers/make-suite'; -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-deployments'; +import { expect } from 'chai'; +import { createRandomAddress } from '../helpers/misc-utils'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +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-deployments'; -const {utils} = ethers; +const { utils } = ethers; makeSuite('LendingPoolAddressesProvider', (testEnv: TestEnv) => { it('Test the accessibility of the LendingPoolAddressesProvider', async () => { - const {addressesProvider, users} = testEnv; + const { addressesProvider, users } = testEnv; const mockAddress = createRandomAddress(); - const {INVALID_OWNER_REVERT_MSG} = ProtocolErrors; + const { INVALID_OWNER_REVERT_MSG } = ProtocolErrors; await addressesProvider.transferOwnership(users[1].address); @@ -30,10 +30,7 @@ makeSuite('LendingPoolAddressesProvider', (testEnv: TestEnv) => { } await expect( - addressesProvider.setAddress( - utils.keccak256(utils.toUtf8Bytes('RANDOM_ID')), - mockAddress - ) + addressesProvider.setAddress(utils.keccak256(utils.toUtf8Bytes('RANDOM_ID')), mockAddress) ).to.be.revertedWith(INVALID_OWNER_REVERT_MSG); await expect( @@ -42,16 +39,14 @@ makeSuite('LendingPoolAddressesProvider', (testEnv: TestEnv) => { mockAddress ) ).to.be.revertedWith(INVALID_OWNER_REVERT_MSG); - }); it('Tests adding a proxied address with `setAddressAsProxy()`', async () => { - const {addressesProvider, users} = testEnv; - const {INVALID_OWNER_REVERT_MSG} = ProtocolErrors; + const { addressesProvider, users } = testEnv; + const { INVALID_OWNER_REVERT_MSG } = ProtocolErrors; const currentAddressesProviderOwner = users[1]; - const mockLendingPool = await deployLendingPool(); const proxiedAddressId = utils.keccak256(utils.toUtf8Bytes('RANDOM_PROXIED')); @@ -74,10 +69,9 @@ makeSuite('LendingPoolAddressesProvider', (testEnv: TestEnv) => { expect(proxiedAddressSetReceipt.events[1].args?.hasProxy).to.be.equal(true); }); - it('Tests adding a non proxied address with `setAddress()`', async () => { - const {addressesProvider, users} = testEnv; - const {INVALID_OWNER_REVERT_MSG} = ProtocolErrors; + const { addressesProvider, users } = testEnv; + const { INVALID_OWNER_REVERT_MSG } = ProtocolErrors; const currentAddressesProviderOwner = users[1]; const mockNonProxiedAddress = createRandomAddress(); @@ -103,6 +97,5 @@ makeSuite('LendingPoolAddressesProvider', (testEnv: TestEnv) => { mockNonProxiedAddress ); expect(nonProxiedAddressSetReceipt.events[0].args?.hasProxy).to.be.equal(false); - }); }); diff --git a/test/liquidation-underlying.spec.ts b/test/liquidation-underlying.spec.ts index 3d28eaa1..0e37d331 100644 --- a/test/liquidation-underlying.spec.ts +++ b/test/liquidation-underlying.spec.ts @@ -1,33 +1,33 @@ import BigNumber from 'bignumber.js'; -import {DRE, increaseTime} from '../helpers/misc-utils'; -import {APPROVAL_AMOUNT_LENDING_POOL, oneEther} from '../helpers/constants'; -import {convertToCurrencyDecimals} from '../helpers/contracts-helpers'; -import {makeSuite} from './helpers/make-suite'; -import {ProtocolErrors, RateMode} from '../helpers/types'; -import {calcExpectedStableDebtTokenBalance} from './helpers/utils/calculations'; -import {getUserData} from './helpers/utils/helpers'; -import {CommonsConfig} from '../markets/aave/commons'; +import { DRE, increaseTime } from '../helpers/misc-utils'; +import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../helpers/constants'; +import { convertToCurrencyDecimals } from '../helpers/contracts-helpers'; +import { makeSuite } from './helpers/make-suite'; +import { ProtocolErrors, RateMode } from '../helpers/types'; +import { calcExpectedStableDebtTokenBalance } from './helpers/utils/calculations'; +import { getUserData } from './helpers/utils/helpers'; +import { CommonsConfig } from '../markets/aave/commons'; -import {parseEther} from 'ethers/lib/utils'; +import { parseEther } from 'ethers/lib/utils'; const chai = require('chai'); -const {expect} = chai; +const { expect } = chai; makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', (testEnv) => { - const {INVALID_HF} = ProtocolErrors; + const { INVALID_HF } = ProtocolErrors; before('Before LendingPool liquidation: set config', () => { - BigNumber.config({DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN}); + BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); }); after('After LendingPool liquidation: reset config', () => { - BigNumber.config({DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP}); + BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); }); it("It's not possible to liquidate on a non-active collateral or a non active principal", async () => { - const {configurator, weth, pool, users, dai} = testEnv; + const { configurator, weth, pool, users, dai } = testEnv; const user = users[1]; await configurator.deactivateReserve(weth.address); @@ -47,7 +47,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', }); it('Deposits WETH, borrows DAI', async () => { - const {dai, weth, users, pool, oracle} = testEnv; + const { dai, weth, users, pool, oracle } = testEnv; const depositor = users[0]; const borrower = users[1]; @@ -102,7 +102,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', }); it('Drop the health factor below 1', async () => { - const {dai, weth, users, pool, oracle} = testEnv; + const { dai, weth, users, pool, oracle } = testEnv; const borrower = users[1]; const daiPrice = await oracle.getAssetPrice(dai.address); @@ -121,7 +121,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', }); it('Liquidates the borrow', async () => { - const {dai, weth, users, pool, oracle, helpersContract} = testEnv; + const { dai, weth, users, pool, oracle, helpersContract } = testEnv; const liquidator = users[3]; const borrower = users[1]; @@ -226,7 +226,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', }); it('User 3 deposits 1000 USDC, user 4 1 WETH, user 4 borrows - drops HF, liquidates the borrow', async () => { - const {usdc, users, pool, oracle, weth, helpersContract} = testEnv; + const { usdc, users, pool, oracle, weth, helpersContract } = testEnv; const depositor = users[3]; const borrower = users[4]; @@ -379,7 +379,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', }); it('User 4 deposits 10 AAVE - drops HF, liquidates the AAVE, which results on a lower amount being liquidated', async () => { - const {aave, usdc, users, pool, oracle, helpersContract} = testEnv; + const { aave, usdc, users, pool, oracle, helpersContract } = testEnv; const depositor = users[3]; const borrower = users[4]; diff --git a/test/mainnet/check-list.spec.ts b/test/mainnet/check-list.spec.ts index 08416eda..d949884b 100644 --- a/test/mainnet/check-list.spec.ts +++ b/test/mainnet/check-list.spec.ts @@ -1,14 +1,14 @@ -import {MAX_UINT_AMOUNT} from '../../helpers/constants'; -import {convertToCurrencyDecimals} from '../../helpers/contracts-helpers'; -import {makeSuite, TestEnv} from '../helpers/make-suite'; -import {parseEther} from 'ethers/lib/utils'; -import {DRE, waitForTx} from '../../helpers/misc-utils'; -import {BigNumber} from 'ethers'; -import {getStableDebtToken, getVariableDebtToken} from '../../helpers/contracts-getters'; -import {deploySelfdestructTransferMock} from '../../helpers/contracts-deployments'; -import {IUniswapV2Router02Factory} from '../../types/IUniswapV2Router02Factory'; +import { MAX_UINT_AMOUNT } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { makeSuite, TestEnv } from '../helpers/make-suite'; +import { parseEther } from 'ethers/lib/utils'; +import { DRE, waitForTx } from '../../helpers/misc-utils'; +import { BigNumber } from 'ethers'; +import { getStableDebtToken, getVariableDebtToken } from '../../helpers/contracts-getters'; +import { deploySelfdestructTransferMock } from '../../helpers/contracts-deployments'; +import { IUniswapV2Router02Factory } from '../../types/IUniswapV2Router02Factory'; -const {expect} = require('chai'); +const { expect } = require('chai'); const UNISWAP_ROUTER = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'; @@ -17,12 +17,12 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { const depositSize = parseEther('5'); it('Deposit WETH', async () => { - const {users, wethGateway, aWETH, pool} = testEnv; + const { users, wethGateway, aWETH, pool } = testEnv; const user = users[1]; // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -31,7 +31,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Withdraw WETH - Partial', async () => { - const {users, wethGateway, aWETH, pool} = testEnv; + const { users, wethGateway, aWETH, pool } = testEnv; const user = users[1]; const priorEthersBalance = await user.signer.getBalance(); @@ -46,10 +46,10 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { const approveTx = await aWETH .connect(user.signer) .approve(wethGateway.address, MAX_UINT_AMOUNT); - const {gasUsed: approveGas} = await waitForTx(approveTx); + const { gasUsed: approveGas } = await waitForTx(approveTx); // Partial Withdraw and send native Ether to user - const {gasUsed: withdrawGas} = await waitForTx( + const { gasUsed: withdrawGas } = await waitForTx( await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) ); @@ -68,7 +68,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Withdraw WETH - Full', async () => { - const {users, aWETH, wethGateway, pool} = testEnv; + const { users, aWETH, wethGateway, pool } = testEnv; const user = users[1]; const priorEthersBalance = await user.signer.getBalance(); @@ -80,10 +80,10 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { const approveTx = await aWETH .connect(user.signer) .approve(wethGateway.address, MAX_UINT_AMOUNT); - const {gasUsed: approveGas} = await waitForTx(approveTx); + const { gasUsed: approveGas } = await waitForTx(approveTx); // Full withdraw - const {gasUsed: withdrawGas} = await waitForTx( + const { gasUsed: withdrawGas } = await waitForTx( await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) ); @@ -99,17 +99,19 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Borrow stable WETH and Full Repay with ETH', async () => { - const {users, wethGateway, aWETH, weth, pool, helpersContract} = testEnv; + const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; const borrowSize = parseEther('1'); const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); const user = users[1]; - const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address); + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); const stableDebtToken = await getStableDebtToken(stableDebtTokenAddress); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -129,7 +131,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '1', user.address, {value: repaySize}) + .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) ); const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); @@ -137,19 +139,19 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Borrow variable WETH and Full Repay with ETH', async () => { - const {users, wethGateway, aWETH, weth, pool, helpersContract} = testEnv; + const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; const borrowSize = parseEther('1'); const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); const user = users[1]; - const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address ); const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -170,7 +172,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { await waitForTx( await wethGateway .connect(user.signer) - .repayETH(partialPayment, '2', user.address, {value: partialPayment}) + .repayETH(partialPayment, '2', user.address, { value: partialPayment }) ); const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); @@ -180,17 +182,17 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, {value: repaySize}) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); }); it('Borrow ETH via delegateApprove ETH and repays back', async () => { - const {users, wethGateway, aWETH, weth, helpersContract} = testEnv; + const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; const borrowSize = parseEther('1'); const user = users[2]; - const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address ); const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); @@ -199,7 +201,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { expect(priorDebtBalance).to.be.eq(zero); // Deposit WETH with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -222,14 +224,14 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, {value: borrowSize.mul(2)}) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); }); it('Should revert if receiver function receives Ether if not WETH', async () => { - const {users, wethGateway} = testEnv; + const { users, wethGateway } = testEnv; const user = users[0]; const amount = parseEther('1'); @@ -244,7 +246,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Should revert if fallback functions is called with Ether', async () => { - const {users, wethGateway} = testEnv; + const { users, wethGateway } = testEnv; const user = users[0]; const amount = parseEther('1'); const fakeABI = ['function wantToCallFallback()']; @@ -263,7 +265,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Should revert if fallback functions is called', async () => { - const {users, wethGateway} = testEnv; + const { users, wethGateway } = testEnv; const user = users[0]; const fakeABI = ['function wantToCallFallback()']; @@ -281,7 +283,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Getters should retrieve correct state', async () => { - const {aWETH, weth, pool, wethGateway} = testEnv; + const { aWETH, weth, pool, wethGateway } = testEnv; const WETHAddress = await wethGateway.getWETHAddress(); const aWETHAddress = await wethGateway.getAWETHAddress(); @@ -293,7 +295,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Owner can do emergency token recovery', async () => { - const {users, weth, dai, wethGateway, deployer} = testEnv; + const { users, weth, dai, wethGateway, deployer } = testEnv; const user = users[0]; const amount = parseEther('1'); @@ -328,7 +330,7 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { }); it('Owner can do emergency native ETH recovery', async () => { - const {users, wethGateway, deployer} = testEnv; + const { users, wethGateway, deployer } = testEnv; const user = users[0]; const amount = parseEther('1'); const userBalancePriorCall = await user.signer.getBalance(); @@ -339,13 +341,13 @@ makeSuite('Mainnet Check list', (testEnv: TestEnv) => { // Selfdestruct the mock, pointing to WETHGateway address const callTx = await selfdestructContract .connect(user.signer) - .destroyAndTransfer(wethGateway.address, {value: amount}); - const {gasUsed} = await waitForTx(callTx); + .destroyAndTransfer(wethGateway.address, { value: amount }); + const { gasUsed } = await waitForTx(callTx); const gasFees = gasUsed.mul(callTx.gasPrice); const userBalanceAfterCall = await user.signer.getBalance(); expect(userBalanceAfterCall).to.be.eq(userBalancePriorCall.sub(amount).sub(gasFees), ''); - 'User should have lost the funds'; + ('User should have lost the funds'); // Recover the funds from the contract and sends back to the user await wethGateway.connect(deployer.signer).emergencyEtherTransfer(user.address, amount); diff --git a/test/pausable-functions.spec.ts b/test/pausable-functions.spec.ts index 56278f66..2ac975ac 100644 --- a/test/pausable-functions.spec.ts +++ b/test/pausable-functions.spec.ts @@ -1,13 +1,13 @@ -import {makeSuite, TestEnv} from './helpers/make-suite'; -import {ProtocolErrors, RateMode} from '../helpers/types'; -import {APPROVAL_AMOUNT_LENDING_POOL, oneEther} from '../helpers/constants'; -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'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors, RateMode } from '../helpers/types'; +import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../helpers/constants'; +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'); +const { expect } = require('chai'); makeSuite('Pausable Pool', (testEnv: TestEnv) => { let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver; @@ -23,7 +23,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { }); it('User 0 deposits 1000 DAI. Configurator pauses pool. Transfers to user 1 reverts. Configurator unpauses the network and next transfer succees', async () => { - const {users, pool, dai, aDai, configurator} = testEnv; + const { users, pool, dai, aDai, configurator } = testEnv; const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); @@ -78,7 +78,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { }); it('Deposit', async () => { - const {users, pool, dai, aDai, configurator} = testEnv; + const { users, pool, dai, aDai, configurator } = testEnv; const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); @@ -98,7 +98,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { }); it('Withdraw', async () => { - const {users, pool, dai, aDai, configurator} = testEnv; + const { users, pool, dai, aDai, configurator } = testEnv; const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); @@ -123,7 +123,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { }); it('Borrow', async () => { - const {pool, dai, users, configurator} = testEnv; + const { pool, dai, users, configurator } = testEnv; const user = users[1]; // Pause the pool @@ -139,7 +139,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { }); it('Repay', async () => { - const {pool, dai, users, configurator} = testEnv; + const { pool, dai, users, configurator } = testEnv; const user = users[1]; // Pause the pool @@ -155,7 +155,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { }); it('Flash loan', async () => { - const {dai, pool, weth, users, configurator} = testEnv; + const { dai, pool, weth, users, configurator } = testEnv; const caller = users[3]; @@ -185,7 +185,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { }); it('Liquidation call', async () => { - const {users, pool, usdc, oracle, weth, configurator, helpersContract} = testEnv; + const { users, pool, usdc, oracle, weth, configurator, helpersContract } = testEnv; const depositor = users[3]; const borrower = users[4]; @@ -266,7 +266,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { }); it('SwapBorrowRateMode', async () => { - const {pool, weth, dai, usdc, users, configurator} = testEnv; + const { pool, weth, dai, usdc, users, configurator } = testEnv; const user = users[1]; const amountWETHToDeposit = parseEther('10'); const amountDAIToDeposit = parseEther('120'); @@ -295,7 +295,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { }); it('RebalanceStableBorrowRate', async () => { - const {pool, dai, users, configurator} = testEnv; + const { pool, dai, users, configurator } = testEnv; const user = users[1]; // Pause pool await configurator.connect(users[1].signer).setPoolPause(true); @@ -309,7 +309,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { }); it('setUserUseReserveAsCollateral', async () => { - const {pool, weth, users, configurator} = testEnv; + const { pool, weth, users, configurator } = testEnv; const user = users[1]; const amountWETHToDeposit = parseEther('1'); diff --git a/test/scenario.spec.ts b/test/scenario.spec.ts index 50793c0c..13037cfb 100644 --- a/test/scenario.spec.ts +++ b/test/scenario.spec.ts @@ -1,12 +1,12 @@ -import {configuration as actionsConfiguration} from './helpers/actions'; -import {configuration as calculationsConfiguration} from './helpers/utils/calculations'; +import { configuration as actionsConfiguration } from './helpers/actions'; +import { configuration as calculationsConfiguration } from './helpers/utils/calculations'; import fs from 'fs'; import BigNumber from 'bignumber.js'; -import {makeSuite} from './helpers/make-suite'; -import {getReservesConfigByPool} from '../helpers/configuration'; -import {AavePools, iAavePoolAssets, IReserveParams} from '../helpers/types'; -import {executeStory} from './helpers/scenario-engine'; +import { makeSuite } from './helpers/make-suite'; +import { getReservesConfigByPool } from '../helpers/configuration'; +import { AavePools, iAavePoolAssets, IReserveParams } from '../helpers/types'; +import { executeStory } from './helpers/scenario-engine'; const scenarioFolder = './test/helpers/scenarios/'; @@ -20,7 +20,7 @@ fs.readdirSync(scenarioFolder).forEach((file) => { makeSuite(scenario.title, async (testEnv) => { before('Initializing configuration', async () => { // Sets BigNumber for this suite, instead of globally - BigNumber.config({DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN}); + BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage @@ -30,7 +30,7 @@ fs.readdirSync(scenarioFolder).forEach((file) => { }); after('Reset', () => { // Reset BigNumber - BigNumber.config({DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP}); + BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); }); for (const story of scenario.stories) { diff --git a/test/stable-token.spec.ts b/test/stable-token.spec.ts index 1f58965f..ab588a81 100644 --- a/test/stable-token.spec.ts +++ b/test/stable-token.spec.ts @@ -1,13 +1,13 @@ -import {expect} from 'chai'; -import {makeSuite, TestEnv} from './helpers/make-suite'; -import {ProtocolErrors} from '../helpers/types'; -import {getStableDebtToken} from '../helpers/contracts-getters'; +import { expect } from 'chai'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors } from '../helpers/types'; +import { getStableDebtToken } from '../helpers/contracts-getters'; makeSuite('Stable debt token tests', (testEnv: TestEnv) => { - const {CT_CALLER_MUST_BE_LENDING_POOL} = ProtocolErrors; + const { CT_CALLER_MUST_BE_LENDING_POOL } = ProtocolErrors; it('Tries to invoke mint not being the LendingPool', async () => { - const {deployer, pool, dai, helpersContract} = testEnv; + const { deployer, pool, dai, helpersContract } = testEnv; const daiStableDebtTokenAddress = (await helpersContract.getReserveTokensAddresses(dai.address)) .stableDebtTokenAddress; @@ -20,7 +20,7 @@ makeSuite('Stable debt token tests', (testEnv: TestEnv) => { }); it('Tries to invoke burn not being the LendingPool', async () => { - const {deployer, dai, helpersContract} = testEnv; + const { deployer, dai, helpersContract } = testEnv; const daiStableDebtTokenAddress = (await helpersContract.getReserveTokensAddresses(dai.address)) .stableDebtTokenAddress; diff --git a/test/subgraph-scenarios.spec.ts b/test/subgraph-scenarios.spec.ts index c756ce50..27f0b994 100644 --- a/test/subgraph-scenarios.spec.ts +++ b/test/subgraph-scenarios.spec.ts @@ -1,11 +1,11 @@ -import {configuration as actionsConfiguration} from './helpers/actions'; -import {configuration as calculationsConfiguration} from './helpers/utils/calculations'; +import { configuration as actionsConfiguration } from './helpers/actions'; +import { configuration as calculationsConfiguration } from './helpers/utils/calculations'; import BigNumber from 'bignumber.js'; -import {makeSuite} from './helpers/make-suite'; -import {getReservesConfigByPool} from '../helpers/configuration'; -import {AavePools, iAavePoolAssets, IReserveParams} from '../helpers/types'; -import {executeStory} from './helpers/scenario-engine'; +import { makeSuite } from './helpers/make-suite'; +import { getReservesConfigByPool } from '../helpers/configuration'; +import { AavePools, iAavePoolAssets, IReserveParams } from '../helpers/types'; +import { executeStory } from './helpers/scenario-engine'; makeSuite('Subgraph scenario tests', async (testEnv) => { let story: any; @@ -14,7 +14,7 @@ makeSuite('Subgraph scenario tests', async (testEnv) => { const scenario = require(`./helpers/scenarios/borrow-repay-stable`); story = scenario.stories[0]; // Sets BigNumber for this suite, instead of globally - BigNumber.config({DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN}); + BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage @@ -24,7 +24,7 @@ makeSuite('Subgraph scenario tests', async (testEnv) => { }); after('Reset', () => { // Reset BigNumber - BigNumber.config({DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP}); + BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); }); it('deposit-borrow', async () => { await executeStory(story, testEnv); diff --git a/test/upgradeability.spec.ts b/test/upgradeability.spec.ts index 92ab1ee1..28e1c335 100644 --- a/test/upgradeability.spec.ts +++ b/test/upgradeability.spec.ts @@ -1,11 +1,11 @@ -import {expect} from 'chai'; -import {makeSuite, TestEnv} from './helpers/make-suite'; -import {ProtocolErrors, eContractid} from '../helpers/types'; -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 { expect } from 'chai'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors, eContractid } from '../helpers/types'; +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, getMockStableDebtToken, @@ -19,13 +19,13 @@ import { } from '../helpers/contracts-deployments'; makeSuite('Upgradeability', (testEnv: TestEnv) => { - const {CALLER_NOT_POOL_ADMIN} = ProtocolErrors; + const { CALLER_NOT_POOL_ADMIN } = ProtocolErrors; let newATokenAddress: string; let newStableTokenAddress: string; let newVariableTokenAddress: string; before('deploying instances', async () => { - const {dai, pool} = testEnv; + const { dai, pool } = testEnv; const aTokenInstance = await deployMockAToken([ pool.address, dai.address, @@ -57,7 +57,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { }); it('Tries to update the DAI Atoken implementation with a different address than the lendingPoolManager', async () => { - const {dai, configurator, users} = testEnv; + const { dai, configurator, users } = testEnv; await expect( configurator.connect(users[1].signer).updateAToken(dai.address, newATokenAddress) @@ -65,7 +65,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { }); it('Upgrades the DAI Atoken implementation ', async () => { - const {dai, configurator, aDai} = testEnv; + const { dai, configurator, aDai } = testEnv; const name = await (await getAToken(newATokenAddress)).name(); @@ -77,7 +77,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { }); it('Tries to update the DAI Stable debt token implementation with a different address than the lendingPoolManager', async () => { - const {dai, configurator, users} = testEnv; + const { dai, configurator, users } = testEnv; await expect( configurator @@ -87,13 +87,13 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { }); it('Upgrades the DAI stable debt token implementation ', async () => { - const {dai, configurator, pool, helpersContract} = testEnv; + const { dai, configurator, pool, helpersContract } = testEnv; const name = await (await getAToken(newATokenAddress)).name(); await configurator.updateStableDebtToken(dai.address, newStableTokenAddress); - const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(dai.address); + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses(dai.address); const debtToken = await getMockStableDebtToken(stableDebtTokenAddress); @@ -103,7 +103,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { }); it('Tries to update the DAI variable debt token implementation with a different address than the lendingPoolManager', async () => { - const {dai, configurator, users} = testEnv; + const { dai, configurator, users } = testEnv; await expect( configurator @@ -113,13 +113,15 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { }); it('Upgrades the DAI variable debt token implementation ', async () => { - const {dai, configurator, pool, helpersContract} = testEnv; + const { dai, configurator, pool, helpersContract } = testEnv; const name = await (await getAToken(newATokenAddress)).name(); await configurator.updateVariableDebtToken(dai.address, newVariableTokenAddress); - const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(dai.address); + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + dai.address + ); const debtToken = await getMockVariableDebtToken(variableDebtTokenAddress); diff --git a/test/variable-debt-token.spec.ts b/test/variable-debt-token.spec.ts index 71dbecd2..0faf7087 100644 --- a/test/variable-debt-token.spec.ts +++ b/test/variable-debt-token.spec.ts @@ -1,13 +1,13 @@ -import {expect} from 'chai'; -import {makeSuite, TestEnv} from './helpers/make-suite'; -import {ProtocolErrors, TokenContractId, eContractid} from '../helpers/types'; -import {getVariableDebtToken} from '../helpers/contracts-getters'; +import { expect } from 'chai'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors, TokenContractId, eContractid } from '../helpers/types'; +import { getVariableDebtToken } from '../helpers/contracts-getters'; makeSuite('Variable debt token tests', (testEnv: TestEnv) => { - const {CT_CALLER_MUST_BE_LENDING_POOL} = ProtocolErrors; + const { CT_CALLER_MUST_BE_LENDING_POOL } = ProtocolErrors; it('Tries to invoke mint not being the LendingPool', async () => { - const {deployer, pool, dai, helpersContract} = testEnv; + const { deployer, pool, dai, helpersContract } = testEnv; const daiVariableDebtTokenAddress = ( await helpersContract.getReserveTokensAddresses(dai.address) @@ -21,7 +21,7 @@ makeSuite('Variable debt token tests', (testEnv: TestEnv) => { }); it('Tries to invoke burn not being the LendingPool', async () => { - const {deployer, pool, dai, helpersContract} = testEnv; + const { deployer, pool, dai, helpersContract } = testEnv; const daiVariableDebtTokenAddress = ( await helpersContract.getReserveTokensAddresses(dai.address) diff --git a/test/weth-gateway.spec.ts b/test/weth-gateway.spec.ts index 20393b85..f564183b 100644 --- a/test/weth-gateway.spec.ts +++ b/test/weth-gateway.spec.ts @@ -1,25 +1,25 @@ -import {MAX_UINT_AMOUNT} from '../helpers/constants'; -import {convertToCurrencyDecimals} from '../helpers/contracts-helpers'; -import {makeSuite, TestEnv} from './helpers/make-suite'; -import {parseEther} from 'ethers/lib/utils'; -import {DRE, waitForTx} from '../helpers/misc-utils'; -import {BigNumber} from 'ethers'; -import {getStableDebtToken, getVariableDebtToken} from '../helpers/contracts-getters'; -import {deploySelfdestructTransferMock} from '../helpers/contracts-deployments'; +import { MAX_UINT_AMOUNT } from '../helpers/constants'; +import { convertToCurrencyDecimals } from '../helpers/contracts-helpers'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { parseEther } from 'ethers/lib/utils'; +import { DRE, waitForTx } from '../helpers/misc-utils'; +import { BigNumber } from 'ethers'; +import { getStableDebtToken, getVariableDebtToken } from '../helpers/contracts-getters'; +import { deploySelfdestructTransferMock } from '../helpers/contracts-deployments'; -const {expect} = require('chai'); +const { expect } = require('chai'); makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => { const zero = BigNumber.from('0'); const depositSize = parseEther('5'); it('Deposit WETH', async () => { - const {users, wethGateway, aWETH, pool} = testEnv; + const { users, wethGateway, aWETH, pool } = testEnv; const user = users[1]; // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -28,7 +28,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Withdraw WETH - Partial', async () => { - const {users, wethGateway, aWETH, pool} = testEnv; + const { users, wethGateway, aWETH, pool } = testEnv; const user = users[1]; const priorEthersBalance = await user.signer.getBalance(); @@ -43,10 +43,10 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => const approveTx = await aWETH .connect(user.signer) .approve(wethGateway.address, MAX_UINT_AMOUNT); - const {gasUsed: approveGas} = await waitForTx(approveTx); + const { gasUsed: approveGas } = await waitForTx(approveTx); // Partial Withdraw and send native Ether to user - const {gasUsed: withdrawGas} = await waitForTx( + const { gasUsed: withdrawGas } = await waitForTx( await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) ); @@ -65,7 +65,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Withdraw WETH - Full', async () => { - const {users, aWETH, wethGateway, pool} = testEnv; + const { users, aWETH, wethGateway, pool } = testEnv; const user = users[1]; const priorEthersBalance = await user.signer.getBalance(); @@ -77,10 +77,10 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => const approveTx = await aWETH .connect(user.signer) .approve(wethGateway.address, MAX_UINT_AMOUNT); - const {gasUsed: approveGas} = await waitForTx(approveTx); + const { gasUsed: approveGas } = await waitForTx(approveTx); // Full withdraw - const {gasUsed: withdrawGas} = await waitForTx( + const { gasUsed: withdrawGas } = await waitForTx( await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) ); @@ -96,17 +96,19 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Borrow stable WETH and Full Repay with ETH', async () => { - const {users, wethGateway, aWETH, weth, pool, helpersContract} = testEnv; + const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; const borrowSize = parseEther('1'); const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); const user = users[1]; - const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address); + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); const stableDebtToken = await getStableDebtToken(stableDebtTokenAddress); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -126,7 +128,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '1', user.address, {value: repaySize}) + .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) ); const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); @@ -134,19 +136,19 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Borrow variable WETH and Full Repay with ETH', async () => { - const {users, wethGateway, aWETH, weth, pool, helpersContract} = testEnv; + const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; const borrowSize = parseEther('1'); const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); const user = users[1]; - const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address ); const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -167,7 +169,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(partialPayment, '2', user.address, {value: partialPayment}) + .repayETH(partialPayment, '2', user.address, { value: partialPayment }) ); const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); @@ -177,17 +179,17 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, {value: repaySize}) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); }); it('Borrow ETH via delegateApprove ETH and repays back', async () => { - const {users, wethGateway, aWETH, weth, helpersContract} = testEnv; + const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; const borrowSize = parseEther('1'); const user = users[2]; - const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address ); const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); @@ -196,7 +198,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => expect(priorDebtBalance).to.be.eq(zero); // Deposit WETH with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize}); + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -219,14 +221,14 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, {value: borrowSize.mul(2)}) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); }); it('Should revert if receiver function receives Ether if not WETH', async () => { - const {users, wethGateway} = testEnv; + const { users, wethGateway } = testEnv; const user = users[0]; const amount = parseEther('1'); @@ -241,7 +243,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Should revert if fallback functions is called with Ether', async () => { - const {users, wethGateway} = testEnv; + const { users, wethGateway } = testEnv; const user = users[0]; const amount = parseEther('1'); const fakeABI = ['function wantToCallFallback()']; @@ -260,7 +262,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Should revert if fallback functions is called', async () => { - const {users, wethGateway} = testEnv; + const { users, wethGateway } = testEnv; const user = users[0]; const fakeABI = ['function wantToCallFallback()']; @@ -278,7 +280,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Getters should retrieve correct state', async () => { - const {aWETH, weth, pool, wethGateway} = testEnv; + const { aWETH, weth, pool, wethGateway } = testEnv; const WETHAddress = await wethGateway.getWETHAddress(); const aWETHAddress = await wethGateway.getAWETHAddress(); @@ -290,7 +292,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Owner can do emergency token recovery', async () => { - const {users, dai, wethGateway, deployer} = testEnv; + const { users, dai, wethGateway, deployer } = testEnv; const user = users[0]; const amount = parseEther('1'); @@ -316,7 +318,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => }); it('Owner can do emergency native ETH recovery', async () => { - const {users, wethGateway, deployer} = testEnv; + const { users, wethGateway, deployer } = testEnv; const user = users[0]; const amount = parseEther('1'); const userBalancePriorCall = await user.signer.getBalance(); @@ -327,13 +329,13 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Selfdestruct the mock, pointing to WETHGateway address const callTx = await selfdestructContract .connect(user.signer) - .destroyAndTransfer(wethGateway.address, {value: amount}); - const {gasUsed} = await waitForTx(callTx); + .destroyAndTransfer(wethGateway.address, { value: amount }); + const { gasUsed } = await waitForTx(callTx); const gasFees = gasUsed.mul(callTx.gasPrice); const userBalanceAfterCall = await user.signer.getBalance(); expect(userBalanceAfterCall).to.be.eq(userBalancePriorCall.sub(amount).sub(gasFees), ''); - 'User should have lost the funds'; + ('User should have lost the funds'); // Recover the funds from the contract and sends back to the user await wethGateway.connect(deployer.signer).emergencyEtherTransfer(user.address, amount); From abb17b004dff94954fb072a96ff266ffc684b584 Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 27 Jan 2021 15:46:04 +0100 Subject: [PATCH 042/219] Fix pre-commit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5d42cf94..c69c2bb2 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ }, "husky": { "hooks": { - "pre-commit": "pretty-quick --pattern 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test/**/*.ts'" + "pre-commit": "pretty-quick --pattern 'contracts/**/*.sol' --pattern 'helpers/**/*.ts' --pattern 'test/**/*.ts' --pattern 'tasks/**/*.ts'" } }, "author": "Aave", From 17af5986808f81b5cf723043758114d6970c8acc Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 27 Jan 2021 15:58:38 +0100 Subject: [PATCH 043/219] Add missing npm run to script --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b30446a1..1b2d473d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,7 +8,7 @@ linter: before_script: - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml build script: - - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env prettier:lint + - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run prettier:lint after_script: - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down From ba054edbd9ba62bd6f9d470b85463ee8387ece4b Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 27 Jan 2021 16:02:44 +0100 Subject: [PATCH 044/219] Test formatting error --- test/scenario.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/scenario.spec.ts b/test/scenario.spec.ts index 13037cfb..9826a03d 100644 --- a/test/scenario.spec.ts +++ b/test/scenario.spec.ts @@ -18,7 +18,8 @@ fs.readdirSync(scenarioFolder).forEach((file) => { const scenario = require(`./helpers/scenarios/${file}`); makeSuite(scenario.title, async (testEnv) => { - before('Initializing configuration', async () => { + before('Initializing configuration', + async () => { // Sets BigNumber for this suite, instead of globally BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); From da0b13757a55518b2780061d97844a109452c4c4 Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 27 Jan 2021 16:57:26 +0100 Subject: [PATCH 045/219] Fix scenario and rename jobs --- .gitlab-ci.yml | 4 ++-- package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1b2d473d..c67ae321 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,14 +1,14 @@ stages: - checks -linter: +lint: stage: checks tags: - aave-build-runner before_script: - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml build script: - - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run prettier:lint + - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run prettier:check after_script: - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean - docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down diff --git a/package.json b/package.json index c69c2bb2..240f4570 100644 --- a/package.json +++ b/package.json @@ -39,8 +39,8 @@ "aave:fork:main": "npm run compile && MAINNET_FORK=true hardhat aave:mainnet", "aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify", "aave:main:full:initialize": "npm run compile && MAINNET_FORK=true full:initialize-tokens --pool Aave", - "prettier:lint": "npx prettier -c 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test/**/*.ts'", - "dev:prettier": "prettier --write .", + "prettier:check": "npx prettier -c 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test/**/*.ts'", + "prettier:write": "prettier --write 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test/**/*.ts'", "ci:test": "npm run compile && npm run test", "ci:clean": "rm -rf ./artifacts ./cache ./types", "print-contracts:kovan": "npm run hardhat:kovan -- print-contracts", From 80cfc7d0feea30e8949c28991862aa918207a608 Mon Sep 17 00:00:00 2001 From: David Racero Date: Thu, 28 Jan 2021 09:51:52 +0100 Subject: [PATCH 046/219] Add fixed format scenario test --- package.json | 2 +- test/scenario.spec.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 240f4570..cdabab0e 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ }, "husky": { "hooks": { - "pre-commit": "pretty-quick --pattern 'contracts/**/*.sol' --pattern 'helpers/**/*.ts' --pattern 'test/**/*.ts' --pattern 'tasks/**/*.ts'" + "pre-commit": "pretty-quick --staged --pattern 'contracts/**/*.sol' --pattern 'helpers/**/*.ts' --pattern 'test/**/*.ts' --pattern 'tasks/**/*.ts'" } }, "author": "Aave", diff --git a/test/scenario.spec.ts b/test/scenario.spec.ts index 9826a03d..13037cfb 100644 --- a/test/scenario.spec.ts +++ b/test/scenario.spec.ts @@ -18,8 +18,7 @@ fs.readdirSync(scenarioFolder).forEach((file) => { const scenario = require(`./helpers/scenarios/${file}`); makeSuite(scenario.title, async (testEnv) => { - before('Initializing configuration', - async () => { + before('Initializing configuration', async () => { // Sets BigNumber for this suite, instead of globally BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); From 80fd095723d4df74ec789268611c850b98a6cbbd Mon Sep 17 00:00:00 2001 From: eboado Date: Thu, 28 Jan 2021 11:05:19 +0100 Subject: [PATCH 047/219] - Implemented protocol changes to enable re-usage of implementations. --- .../deployments/ATokensAndRatesHelper.sol | 103 ++--- .../StableAndVariableTokensHelper.sol | 27 +- contracts/interfaces/IAToken.sol | 9 +- contracts/interfaces/IInitializableAToken.sol | 32 ++ .../interfaces/IInitializableDebtToken.sol | 30 ++ .../interfaces/ILendingPoolConfigurator.sol | 176 +++++++++ contracts/interfaces/IStableDebtToken.sol | 10 +- contracts/interfaces/ITokenConfiguration.sol | 14 - contracts/interfaces/IVariableDebtToken.sol | 9 +- contracts/mocks/upgradeability/MockAToken.sol | 32 +- .../upgradeability/MockStableDebtToken.sol | 11 - .../upgradeability/MockVariableDebtToken.sol | 17 - .../protocol/lendingpool/LendingPool.sol | 46 ++- .../lendingpool/LendingPoolConfigurator.sol | 374 +++++++----------- .../lendingpool/LendingPoolStorage.sol | 6 + contracts/protocol/tokenization/AToken.sol | 133 ++++--- .../tokenization/DelegationAwareAToken.sol | 23 +- .../tokenization/IncentivizedERC20.sol | 28 +- .../protocol/tokenization/StableDebtToken.sol | 78 +++- .../tokenization/VariableDebtToken.sol | 74 +++- .../tokenization/base/DebtTokenBase.sol | 46 +-- 21 files changed, 741 insertions(+), 537 deletions(-) create mode 100644 contracts/interfaces/IInitializableAToken.sol create mode 100644 contracts/interfaces/IInitializableDebtToken.sol create mode 100644 contracts/interfaces/ILendingPoolConfigurator.sol delete mode 100644 contracts/interfaces/ITokenConfiguration.sol diff --git a/contracts/deployments/ATokensAndRatesHelper.sol b/contracts/deployments/ATokensAndRatesHelper.sol index a29dc6f2..400f7ca6 100644 --- a/contracts/deployments/ATokensAndRatesHelper.sol +++ b/contracts/deployments/ATokensAndRatesHelper.sol @@ -20,6 +20,20 @@ contract ATokensAndRatesHelper is Ownable { address private poolConfigurator; event deployedContracts(address aToken, address strategy); + struct InitDeploymentInput { + address asset; + uint256[6] rates; + } + + struct ConfigureReserveInput { + address asset; + uint256 baseLTV; + uint256 liquidationThreshold; + uint256 liquidationBonus; + uint256 reserveFactor; + bool stableBorrowingEnabled; + } + constructor( address payable _pool, address _addressesProvider, @@ -30,93 +44,40 @@ contract ATokensAndRatesHelper is Ownable { poolConfigurator = _poolConfigurator; } - function initDeployment( - address[] calldata assets, - string[] calldata symbols, - uint256[6][] calldata rates, - address treasuryAddress, - address incentivesController - ) external onlyOwner { - require(assets.length == symbols.length, 't Arrays not same length'); - require(rates.length == symbols.length, 'r Arrays not same length'); - for (uint256 i = 0; i < assets.length; i++) { + function initDeployment(InitDeploymentInput[] calldata inputParams) external onlyOwner { + for (uint256 i = 0; i < inputParams.length; i++) { emit deployedContracts( - address( - new AToken( - LendingPool(pool), - assets[i], - treasuryAddress, - StringLib.concat('Aave interest bearing ', symbols[i]), - StringLib.concat('a', symbols[i]), - incentivesController - ) - ), + address(new AToken()), address( new DefaultReserveInterestRateStrategy( LendingPoolAddressesProvider(addressesProvider), - rates[i][0], - rates[i][1], - rates[i][2], - rates[i][3], - rates[i][4], - rates[i][5] + inputParams[i].rates[0], + inputParams[i].rates[1], + inputParams[i].rates[2], + inputParams[i].rates[3], + inputParams[i].rates[4], + inputParams[i].rates[5] ) ) ); } } - function initReserve( - address[] calldata stables, - address[] calldata variables, - address[] calldata aTokens, - address[] calldata strategies, - uint8[] calldata reserveDecimals - ) external onlyOwner { - require(variables.length == stables.length); - require(aTokens.length == stables.length); - require(strategies.length == stables.length); - require(reserveDecimals.length == stables.length); - - for (uint256 i = 0; i < stables.length; i++) { - LendingPoolConfigurator(poolConfigurator).initReserve( - aTokens[i], - stables[i], - variables[i], - reserveDecimals[i], - strategies[i] - ); - } - } - - function configureReserves( - address[] calldata assets, - uint256[] calldata baseLTVs, - uint256[] calldata liquidationThresholds, - uint256[] calldata liquidationBonuses, - uint256[] calldata reserveFactors, - bool[] calldata stableBorrowingEnabled - ) external onlyOwner { - require(baseLTVs.length == assets.length); - require(liquidationThresholds.length == assets.length); - require(liquidationBonuses.length == assets.length); - require(stableBorrowingEnabled.length == assets.length); - require(reserveFactors.length == assets.length); - + function configureReserves(ConfigureReserveInput[] calldata inputParams) external onlyOwner { LendingPoolConfigurator configurator = LendingPoolConfigurator(poolConfigurator); - for (uint256 i = 0; i < assets.length; i++) { + for (uint256 i = 0; i < inputParams.length; i++) { configurator.configureReserveAsCollateral( - assets[i], - baseLTVs[i], - liquidationThresholds[i], - liquidationBonuses[i] + inputParams[i].asset, + inputParams[i].baseLTV, + inputParams[i].liquidationThreshold, + inputParams[i].liquidationBonus ); configurator.enableBorrowingOnReserve( - assets[i], - stableBorrowingEnabled[i] + inputParams[i].asset, + inputParams[i].stableBorrowingEnabled ); - configurator.setReserveFactor(assets[i], reserveFactors[i]); + configurator.setReserveFactor(inputParams[i].asset, inputParams[i].reserveFactor); } } } diff --git a/contracts/deployments/StableAndVariableTokensHelper.sol b/contracts/deployments/StableAndVariableTokensHelper.sol index 8f76bbe1..e31651f3 100644 --- a/contracts/deployments/StableAndVariableTokensHelper.sol +++ b/contracts/deployments/StableAndVariableTokensHelper.sol @@ -18,34 +18,11 @@ contract StableAndVariableTokensHelper is Ownable { addressesProvider = _addressesProvider; } - function initDeployment( - address[] calldata tokens, - string[] calldata symbols, - address incentivesController - ) external onlyOwner { + function initDeployment(address[] calldata tokens, string[] calldata symbols) 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++) { - emit deployedContracts( - address( - new StableDebtToken( - pool, - tokens[i], - StringLib.concat('Aave stable debt bearing ', symbols[i]), - StringLib.concat('stableDebt', symbols[i]), - incentivesController - ) - ), - address( - new VariableDebtToken( - pool, - tokens[i], - StringLib.concat('Aave variable debt bearing ', symbols[i]), - StringLib.concat('variableDebt', symbols[i]), - incentivesController - ) - ) - ); + emit deployedContracts(address(new StableDebtToken()), address(new VariableDebtToken())); } } diff --git a/contracts/interfaces/IAToken.sol b/contracts/interfaces/IAToken.sol index 5fa1a4f0..ca338270 100644 --- a/contracts/interfaces/IAToken.sol +++ b/contracts/interfaces/IAToken.sol @@ -3,8 +3,10 @@ pragma solidity 0.6.12; import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; import {IScaledBalanceToken} from './IScaledBalanceToken.sol'; +import {IInitializableAToken} from './IInitializableAToken.sol'; +import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; -interface IAToken is IERC20, IScaledBalanceToken { +interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken { /** * @dev Emitted after the mint action * @param from The address performing the mint @@ -85,4 +87,9 @@ interface IAToken is IERC20, IScaledBalanceToken { * @return The amount transferred **/ function transferUnderlyingTo(address user, uint256 amount) external returns (uint256); + + /** + * @dev Returns the address of the incentives controller contract + **/ + function getIncentivesController() external view returns (IAaveIncentivesController); } diff --git a/contracts/interfaces/IInitializableAToken.sol b/contracts/interfaces/IInitializableAToken.sol new file mode 100644 index 00000000..9cffe6ce --- /dev/null +++ b/contracts/interfaces/IInitializableAToken.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; + +import {ILendingPool} from './ILendingPool.sol'; +import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; + +/** + * @title IInitializableAToken + * @notice Interface for the initialize function on AToken + * @author Aave + **/ +interface IInitializableAToken { + /** + * @dev Initializes the aToken + * @param pool The address of the lending pool where this aToken will be used + * @param treasury The address of the Aave treasury, receiving the fees on this aToken + * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) + * @param incentivesController The smart contract managing potential incentives distribution + * @param aTokenDecimals The decimals of the aToken, same as the underlying asset's + * @param aTokenName The name of the aToken + * @param aTokenSymbol The symbol of the aToken + */ + function initialize( + ILendingPool pool, + address treasury, + address underlyingAsset, + IAaveIncentivesController incentivesController, + uint8 aTokenDecimals, + string calldata aTokenName, + string calldata aTokenSymbol + ) external; +} diff --git a/contracts/interfaces/IInitializableDebtToken.sol b/contracts/interfaces/IInitializableDebtToken.sol new file mode 100644 index 00000000..0a85c968 --- /dev/null +++ b/contracts/interfaces/IInitializableDebtToken.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; + +import {ILendingPool} from './ILendingPool.sol'; +import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; + +/** + * @title IInitializableDebtToken + * @notice Interface for the initialize function common between debt tokens + * @author Aave + **/ +interface IInitializableDebtToken { + /** + * @dev Initializes the debt token. + * @param pool The address of the lending pool where this aToken will be used + * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) + * @param incentivesController The smart contract managing potential incentives distribution + * @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's + * @param debtTokenName The name of the token + * @param debtTokenSymbol The symbol of the token + */ + function initialize( + ILendingPool pool, + address underlyingAsset, + IAaveIncentivesController incentivesController, + uint8 debtTokenDecimals, + string memory debtTokenName, + string memory debtTokenSymbol + ) external; +} diff --git a/contracts/interfaces/ILendingPoolConfigurator.sol b/contracts/interfaces/ILendingPoolConfigurator.sol new file mode 100644 index 00000000..8981db6c --- /dev/null +++ b/contracts/interfaces/ILendingPoolConfigurator.sol @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +interface ILendingPoolConfigurator { + struct InitReserveInput { + address aTokenImpl; + address stableDebtTokenImpl; + address variableDebtTokenImpl; + uint8 underlyingAssetDecimals; + address interestRateStrategyAddress; + address underlyingAsset; + address treasury; + address incentivesController; + string underlyingAssetName; + string aTokenName; + string aTokenSymbol; + string variableDebtTokenName; + string variableDebtTokenSymbol; + string stableDebtTokenName; + string stableDebtTokenSymbol; + } + + struct UpdateATokenInput { + address asset; + address treasury; + address incentivesController; + string name; + string symbol; + address implementation; + } + + struct UpdateDebtTokenInput { + address asset; + address incentivesController; + string name; + string symbol; + address implementation; + } + + /** + * @dev Emitted when a reserve is initialized. + * @param asset The address of the underlying asset of the reserve + * @param aToken The address of the associated aToken contract + * @param stableDebtToken The address of the associated stable rate debt token + * @param variableDebtToken The address of the associated variable rate debt token + * @param interestRateStrategyAddress The address of the interest rate strategy for the reserve + **/ + event ReserveInitialized( + address indexed asset, + address indexed aToken, + address stableDebtToken, + address variableDebtToken, + address interestRateStrategyAddress + ); + + /** + * @dev Emitted when borrowing is enabled on a reserve + * @param asset The address of the underlying asset of the reserve + * @param stableRateEnabled True if stable rate borrowing is enabled, false otherwise + **/ + event BorrowingEnabledOnReserve(address indexed asset, bool stableRateEnabled); + + /** + * @dev Emitted when borrowing is disabled on a reserve + * @param asset The address of the underlying asset of the reserve + **/ + event BorrowingDisabledOnReserve(address indexed asset); + + /** + * @dev Emitted when the collateralization risk parameters for the specified asset are updated. + * @param asset The address of the underlying asset of the reserve + * @param ltv The loan to value of the asset when used as collateral + * @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized + * @param liquidationBonus The bonus liquidators receive to liquidate this asset + **/ + event CollateralConfigurationChanged( + address indexed asset, + uint256 ltv, + uint256 liquidationThreshold, + uint256 liquidationBonus + ); + + /** + * @dev Emitted when stable rate borrowing is enabled on a reserve + * @param asset The address of the underlying asset of the reserve + **/ + event StableRateEnabledOnReserve(address indexed asset); + + /** + * @dev Emitted when stable rate borrowing is disabled on a reserve + * @param asset The address of the underlying asset of the reserve + **/ + event StableRateDisabledOnReserve(address indexed asset); + + /** + * @dev Emitted when a reserve is activated + * @param asset The address of the underlying asset of the reserve + **/ + event ReserveActivated(address indexed asset); + + /** + * @dev Emitted when a reserve is deactivated + * @param asset The address of the underlying asset of the reserve + **/ + event ReserveDeactivated(address indexed asset); + + /** + * @dev Emitted when a reserve is frozen + * @param asset The address of the underlying asset of the reserve + **/ + event ReserveFrozen(address indexed asset); + + /** + * @dev Emitted when a reserve is unfrozen + * @param asset The address of the underlying asset of the reserve + **/ + event ReserveUnfrozen(address indexed asset); + + /** + * @dev Emitted when a reserve factor is updated + * @param asset The address of the underlying asset of the reserve + * @param factor The new reserve factor + **/ + event ReserveFactorChanged(address indexed asset, uint256 factor); + + /** + * @dev Emitted when the reserve decimals are updated + * @param asset The address of the underlying asset of the reserve + * @param decimals The new decimals + **/ + event ReserveDecimalsChanged(address indexed asset, uint256 decimals); + + /** + * @dev Emitted when a reserve interest strategy contract is updated + * @param asset The address of the underlying asset of the reserve + * @param strategy The new address of the interest strategy contract + **/ + event ReserveInterestRateStrategyChanged(address indexed asset, address strategy); + + /** + * @dev Emitted when an aToken implementation is upgraded + * @param asset The address of the underlying asset of the reserve + * @param proxy The aToken proxy address + * @param implementation The new aToken implementation + **/ + event ATokenUpgraded( + address indexed asset, + address indexed proxy, + address indexed implementation + ); + + /** + * @dev Emitted when the implementation of a stable debt token is upgraded + * @param asset The address of the underlying asset of the reserve + * @param proxy The stable debt token proxy address + * @param implementation The new aToken implementation + **/ + event StableDebtTokenUpgraded( + address indexed asset, + address indexed proxy, + address indexed implementation + ); + + /** + * @dev Emitted when the implementation of a variable debt token is upgraded + * @param asset The address of the underlying asset of the reserve + * @param proxy The variable debt token proxy address + * @param implementation The new aToken implementation + **/ + event VariableDebtTokenUpgraded( + address indexed asset, + address indexed proxy, + address indexed implementation + ); +} diff --git a/contracts/interfaces/IStableDebtToken.sol b/contracts/interfaces/IStableDebtToken.sol index c24750bc..e39cf8b5 100644 --- a/contracts/interfaces/IStableDebtToken.sol +++ b/contracts/interfaces/IStableDebtToken.sol @@ -1,6 +1,9 @@ // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; +import {IInitializableDebtToken} from './IInitializableDebtToken.sol'; +import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; + /** * @title IStableDebtToken * @notice Defines the interface for the stable debt token @@ -8,7 +11,7 @@ pragma solidity 0.6.12; * @author Aave **/ -interface IStableDebtToken { +interface IStableDebtToken is IInitializableDebtToken { /** * @dev Emitted when new stable debt is minted * @param user The address of the user who triggered the minting @@ -122,4 +125,9 @@ interface IStableDebtToken { * @return The debt balance of the user since the last burn/mint action **/ function principalBalanceOf(address user) external view returns (uint256); + + /** + * @dev Returns the address of the incentives controller contract + **/ + function getIncentivesController() external view returns (IAaveIncentivesController); } diff --git a/contracts/interfaces/ITokenConfiguration.sol b/contracts/interfaces/ITokenConfiguration.sol deleted file mode 100644 index 94607bcd..00000000 --- a/contracts/interfaces/ITokenConfiguration.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.6.12; - -/** - * @title ITokenConfiguration - * @author Aave - * @dev Common interface between aTokens and debt tokens to fetch the - * token configuration - **/ -interface ITokenConfiguration { - function UNDERLYING_ASSET_ADDRESS() external view returns (address); - - function POOL() external view returns (address); -} diff --git a/contracts/interfaces/IVariableDebtToken.sol b/contracts/interfaces/IVariableDebtToken.sol index 6a0c1555..d88c25fc 100644 --- a/contracts/interfaces/IVariableDebtToken.sol +++ b/contracts/interfaces/IVariableDebtToken.sol @@ -2,13 +2,15 @@ pragma solidity 0.6.12; import {IScaledBalanceToken} from './IScaledBalanceToken.sol'; +import {IInitializableDebtToken} from './IInitializableDebtToken.sol'; +import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; /** * @title IVariableDebtToken * @author Aave * @notice Defines the basic interface for a variable debt token. **/ -interface IVariableDebtToken is IScaledBalanceToken { +interface IVariableDebtToken is IScaledBalanceToken, IInitializableDebtToken { /** * @dev Emitted after the mint action * @param from The address performing the mint @@ -52,4 +54,9 @@ interface IVariableDebtToken is IScaledBalanceToken { uint256 amount, uint256 index ) external; + + /** + * @dev Returns the address of the incentives controller contract + **/ + function getIncentivesController() external view returns (IAaveIncentivesController); } diff --git a/contracts/mocks/upgradeability/MockAToken.sol b/contracts/mocks/upgradeability/MockAToken.sol index f0eda38c..7e7b6f2a 100644 --- a/contracts/mocks/upgradeability/MockAToken.sol +++ b/contracts/mocks/upgradeability/MockAToken.sol @@ -2,39 +2,11 @@ pragma solidity 0.6.12; import {AToken} from '../../protocol/tokenization/AToken.sol'; -import {LendingPool} from '../../protocol/lendingpool/LendingPool.sol'; +import {ILendingPool} from '../../interfaces/ILendingPool.sol'; +import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; contract MockAToken is AToken { - constructor( - LendingPool pool, - address underlyingAssetAddress, - address reserveTreasury, - string memory tokenName, - string memory tokenSymbol, - address incentivesController - ) - public - AToken( - pool, - underlyingAssetAddress, - reserveTreasury, - tokenName, - tokenSymbol, - incentivesController - ) - {} - function getRevision() internal pure override returns (uint256) { return 0x2; } - - function initialize( - uint8 _underlyingAssetDecimals, - string calldata _tokenName, - string calldata _tokenSymbol - ) external virtual override initializer { - _setName(_tokenName); - _setSymbol(_tokenSymbol); - _setDecimals(_underlyingAssetDecimals); - } } diff --git a/contracts/mocks/upgradeability/MockStableDebtToken.sol b/contracts/mocks/upgradeability/MockStableDebtToken.sol index 5030c171..cbc66664 100644 --- a/contracts/mocks/upgradeability/MockStableDebtToken.sol +++ b/contracts/mocks/upgradeability/MockStableDebtToken.sol @@ -4,17 +4,6 @@ pragma solidity 0.6.12; import {StableDebtToken} from '../../protocol/tokenization/StableDebtToken.sol'; contract MockStableDebtToken is StableDebtToken { - constructor( - address _pool, - address _underlyingAssetAddress, - string memory _tokenName, - string memory _tokenSymbol, - address incentivesController - ) - public - StableDebtToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol, incentivesController) - {} - function getRevision() internal pure override returns (uint256) { return 0x2; } diff --git a/contracts/mocks/upgradeability/MockVariableDebtToken.sol b/contracts/mocks/upgradeability/MockVariableDebtToken.sol index 0a9a03aa..497682c3 100644 --- a/contracts/mocks/upgradeability/MockVariableDebtToken.sol +++ b/contracts/mocks/upgradeability/MockVariableDebtToken.sol @@ -4,23 +4,6 @@ pragma solidity 0.6.12; import {VariableDebtToken} from '../../protocol/tokenization/VariableDebtToken.sol'; contract MockVariableDebtToken is VariableDebtToken { - constructor( - address _pool, - address _underlyingAssetAddress, - string memory _tokenName, - string memory _tokenSymbol, - address incentivesController - ) - public - VariableDebtToken( - _pool, - _underlyingAssetAddress, - _tokenName, - _tokenSymbol, - incentivesController - ) - {} - function getRevision() internal pure override returns (uint256) { return 0x2; } diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 7c48f237..75e80230 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -49,10 +49,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage using PercentageMath for uint256; using SafeERC20 for IERC20; - //main configuration parameters - uint256 public constant MAX_STABLE_RATE_BORROW_SIZE_PERCENT = 2500; - uint256 public constant FLASHLOAN_PREMIUM_TOTAL = 9; - uint256 public constant MAX_NUMBER_RESERVES = 128; uint256 public constant LENDINGPOOL_REVISION = 0x2; modifier whenNotPaused() { @@ -86,9 +82,20 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage * - Caching the address of the LendingPoolAddressesProvider in order to reduce gas consumption * on subsequent operations * @param provider The address of the LendingPoolAddressesProvider + * @param maxStableRateBorrowSizePercent The percentage of available liquidity that can be borrowed at once at stable rate + * @param flashLoanPremiumTotal The fee on flash loans + * @param maxNumberOfReserves Maximum number of reserves supported to be listed in this LendingPool **/ - function initialize(ILendingPoolAddressesProvider provider) public initializer { + function initialize( + ILendingPoolAddressesProvider provider, + uint256 maxStableRateBorrowSizePercent, + uint256 flashLoanPremiumTotal, + uint256 maxNumberOfReserves + ) public initializer { _addressesProvider = provider; + _maxStableRateBorrowSizePercent = maxStableRateBorrowSizePercent; + _flashLoanPremiumTotal = flashLoanPremiumTotal; + _maxNumberOfReserves = maxNumberOfReserves; } /** @@ -144,7 +151,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage address asset, uint256 amount, address to - ) external override whenNotPaused returns (uint256) { + ) external override whenNotPaused returns (uint256) { DataTypes.ReserveData storage reserve = _reserves[asset]; address aToken = reserve.aTokenAddress; @@ -499,7 +506,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage for (vars.i = 0; vars.i < assets.length; vars.i++) { aTokenAddresses[vars.i] = _reserves[assets[vars.i]].aTokenAddress; - premiums[vars.i] = amounts[vars.i].mul(FLASHLOAN_PREMIUM_TOTAL).div(10000); + premiums[vars.i] = amounts[vars.i].mul(_flashLoanPremiumTotal).div(10000); IAToken(aTokenAddresses[vars.i]).transferUnderlyingTo(receiverAddress, amounts[vars.i]); } @@ -703,6 +710,27 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage return _addressesProvider; } + /** + * @dev Returns the percentage of available liquidity that can be borrowed at once at stable rate + */ + function MAX_STABLE_RATE_BORROW_SIZE_PERCENT() public view returns (uint256) { + return _maxStableRateBorrowSizePercent; + } + + /** + * @dev Returns the fee on flash loans + */ + function FLASHLOAN_PREMIUM_TOTAL() public view returns (uint256) { + return _flashLoanPremiumTotal; + } + + /** + * @dev Returns the maximum number of reserves supported to be listed in this LendingPool + */ + function MAX_NUMBER_RESERVES() public view returns (uint256) { + return _maxNumberOfReserves; + } + /** * @dev Validates and finalizes an aToken transfer * - Only callable by the overlying aToken of the `asset` @@ -847,7 +875,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage vars.amount, amountInETH, vars.interestRateMode, - MAX_STABLE_RATE_BORROW_SIZE_PERCENT, + _maxStableRateBorrowSizePercent, _reserves, userConfig, _reservesList, @@ -909,7 +937,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage function _addReserveToList(address asset) internal { uint256 reservesCount = _reservesCount; - require(reservesCount < MAX_NUMBER_RESERVES, Errors.LP_NO_MORE_RESERVES_ALLOWED); + require(reservesCount < _maxNumberOfReserves, Errors.LP_NO_MORE_RESERVES_ALLOWED); bool reserveAlreadyAdded = _reserves[asset].id != 0 || _reservesList[0] == asset; diff --git a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol index bb3fb774..f42415ca 100644 --- a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol @@ -10,11 +10,14 @@ import { import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol'; import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; import {ILendingPool} from '../../interfaces/ILendingPool.sol'; -import {ITokenConfiguration} from '../../interfaces/ITokenConfiguration.sol'; import {IERC20Detailed} from '../../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; import {Errors} from '../libraries/helpers/Errors.sol'; import {PercentageMath} from '../libraries/math/PercentageMath.sol'; import {DataTypes} from '../libraries/types/DataTypes.sol'; +import {IInitializableDebtToken} from '../../interfaces/IInitializableDebtToken.sol'; +import {IInitializableAToken} from '../../interfaces/IInitializableAToken.sol'; +import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; +import {ILendingPoolConfigurator} from '../../interfaces/ILendingPoolConfigurator.sol'; /** * @title LendingPoolConfigurator contract @@ -22,147 +25,11 @@ import {DataTypes} from '../libraries/types/DataTypes.sol'; * @dev Implements the configuration methods for the Aave protocol **/ -contract LendingPoolConfigurator is VersionedInitializable { +contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigurator { using SafeMath for uint256; using PercentageMath for uint256; using ReserveConfiguration for DataTypes.ReserveConfigurationMap; - /** - * @dev Emitted when a reserve is initialized. - * @param asset The address of the underlying asset of the reserve - * @param aToken The address of the associated aToken contract - * @param stableDebtToken The address of the associated stable rate debt token - * @param variableDebtToken The address of the associated variable rate debt token - * @param interestRateStrategyAddress The address of the interest rate strategy for the reserve - **/ - event ReserveInitialized( - address indexed asset, - address indexed aToken, - address stableDebtToken, - address variableDebtToken, - address interestRateStrategyAddress - ); - - /** - * @dev Emitted when borrowing is enabled on a reserve - * @param asset The address of the underlying asset of the reserve - * @param stableRateEnabled True if stable rate borrowing is enabled, false otherwise - **/ - event BorrowingEnabledOnReserve(address indexed asset, bool stableRateEnabled); - - /** - * @dev Emitted when borrowing is disabled on a reserve - * @param asset The address of the underlying asset of the reserve - **/ - event BorrowingDisabledOnReserve(address indexed asset); - - /** - * @dev Emitted when the collateralization risk parameters for the specified asset are updated. - * @param asset The address of the underlying asset of the reserve - * @param ltv The loan to value of the asset when used as collateral - * @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized - * @param liquidationBonus The bonus liquidators receive to liquidate this asset - **/ - event CollateralConfigurationChanged( - address indexed asset, - uint256 ltv, - uint256 liquidationThreshold, - uint256 liquidationBonus - ); - - /** - * @dev Emitted when stable rate borrowing is enabled on a reserve - * @param asset The address of the underlying asset of the reserve - **/ - event StableRateEnabledOnReserve(address indexed asset); - - /** - * @dev Emitted when stable rate borrowing is disabled on a reserve - * @param asset The address of the underlying asset of the reserve - **/ - event StableRateDisabledOnReserve(address indexed asset); - - /** - * @dev Emitted when a reserve is activated - * @param asset The address of the underlying asset of the reserve - **/ - event ReserveActivated(address indexed asset); - - /** - * @dev Emitted when a reserve is deactivated - * @param asset The address of the underlying asset of the reserve - **/ - event ReserveDeactivated(address indexed asset); - - /** - * @dev Emitted when a reserve is frozen - * @param asset The address of the underlying asset of the reserve - **/ - event ReserveFrozen(address indexed asset); - - /** - * @dev Emitted when a reserve is unfrozen - * @param asset The address of the underlying asset of the reserve - **/ - event ReserveUnfrozen(address indexed asset); - - /** - * @dev Emitted when a reserve factor is updated - * @param asset The address of the underlying asset of the reserve - * @param factor The new reserve factor - **/ - event ReserveFactorChanged(address indexed asset, uint256 factor); - - /** - * @dev Emitted when the reserve decimals are updated - * @param asset The address of the underlying asset of the reserve - * @param decimals The new decimals - **/ - event ReserveDecimalsChanged(address indexed asset, uint256 decimals); - - /** - * @dev Emitted when a reserve interest strategy contract is updated - * @param asset The address of the underlying asset of the reserve - * @param strategy The new address of the interest strategy contract - **/ - event ReserveInterestRateStrategyChanged(address indexed asset, address strategy); - - /** - * @dev Emitted when an aToken implementation is upgraded - * @param asset The address of the underlying asset of the reserve - * @param proxy The aToken proxy address - * @param implementation The new aToken implementation - **/ - event ATokenUpgraded( - address indexed asset, - address indexed proxy, - address indexed implementation - ); - - /** - * @dev Emitted when the implementation of a stable debt token is upgraded - * @param asset The address of the underlying asset of the reserve - * @param proxy The stable debt token proxy address - * @param implementation The new aToken implementation - **/ - event StableDebtTokenUpgraded( - address indexed asset, - address indexed proxy, - address indexed implementation - ); - - /** - * @dev Emitted when the implementation of a variable debt token is upgraded - * @param asset The address of the underlying asset of the reserve - * @param proxy The variable debt token proxy address - * @param implementation The new aToken implementation - **/ - event VariableDebtTokenUpgraded( - address indexed asset, - address indexed proxy, - address indexed implementation - ); - ILendingPoolAddressesProvider internal addressesProvider; ILendingPool internal pool; @@ -191,114 +58,186 @@ contract LendingPoolConfigurator is VersionedInitializable { } /** - * @dev Initializes a reserve - * @param aTokenImpl The address of the aToken contract implementation - * @param stableDebtTokenImpl The address of the stable debt token contract - * @param variableDebtTokenImpl The address of the variable debt token contract - * @param underlyingAssetDecimals The decimals of the reserve underlying asset - * @param interestRateStrategyAddress The address of the interest rate strategy contract for this reserve + * @dev Initializes reserves in batch **/ - function initReserve( - address aTokenImpl, - address stableDebtTokenImpl, - address variableDebtTokenImpl, - uint8 underlyingAssetDecimals, - address interestRateStrategyAddress - ) public onlyPoolAdmin { - address asset = ITokenConfiguration(aTokenImpl).UNDERLYING_ASSET_ADDRESS(); + function batchInitReserve(InitReserveInput[] calldata inputParams) public onlyPoolAdmin { + ILendingPool cachedPool = pool; + for (uint256 i = 0; i < inputParams.length; i++) { + _initReserve(cachedPool, inputParams[i]); + } + } - require( - address(pool) == ITokenConfiguration(aTokenImpl).POOL(), - Errors.LPC_INVALID_ATOKEN_POOL_ADDRESS - ); - require( - address(pool) == ITokenConfiguration(stableDebtTokenImpl).POOL(), - Errors.LPC_INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS - ); - require( - address(pool) == ITokenConfiguration(variableDebtTokenImpl).POOL(), - Errors.LPC_INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS - ); - require( - asset == ITokenConfiguration(stableDebtTokenImpl).UNDERLYING_ASSET_ADDRESS(), - Errors.LPC_INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS - ); - require( - asset == ITokenConfiguration(variableDebtTokenImpl).UNDERLYING_ASSET_ADDRESS(), - Errors.LPC_INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS - ); - - address aTokenProxyAddress = _initTokenWithProxy(aTokenImpl, underlyingAssetDecimals); + function _initReserve(ILendingPool pool, InitReserveInput calldata inputParams) internal { + address aTokenProxyAddress = + _initTokenWithProxy( + inputParams.aTokenImpl, + abi.encodeWithSelector( + IInitializableAToken.initialize.selector, + pool, + inputParams.treasury, + inputParams.underlyingAsset, + IAaveIncentivesController(inputParams.incentivesController), + inputParams.underlyingAssetDecimals, + inputParams.aTokenName, + inputParams.aTokenSymbol + ) + ); address stableDebtTokenProxyAddress = - _initTokenWithProxy(stableDebtTokenImpl, underlyingAssetDecimals); + _initTokenWithProxy( + inputParams.stableDebtTokenImpl, + abi.encodeWithSelector( + IInitializableDebtToken.initialize.selector, + pool, + inputParams.underlyingAsset, + IAaveIncentivesController(inputParams.incentivesController), + inputParams.underlyingAssetDecimals, + inputParams.stableDebtTokenName, + inputParams.stableDebtTokenSymbol + ) + ); address variableDebtTokenProxyAddress = - _initTokenWithProxy(variableDebtTokenImpl, underlyingAssetDecimals); + _initTokenWithProxy( + inputParams.variableDebtTokenImpl, + abi.encodeWithSelector( + IInitializableDebtToken.initialize.selector, + pool, + inputParams.underlyingAsset, + IAaveIncentivesController(inputParams.incentivesController), + inputParams.underlyingAssetDecimals, + inputParams.variableDebtTokenName, + inputParams.variableDebtTokenSymbol + ) + ); pool.initReserve( - asset, + inputParams.underlyingAsset, aTokenProxyAddress, stableDebtTokenProxyAddress, variableDebtTokenProxyAddress, - interestRateStrategyAddress + inputParams.interestRateStrategyAddress ); - DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + DataTypes.ReserveConfigurationMap memory currentConfig = + pool.getConfiguration(inputParams.underlyingAsset); - currentConfig.setDecimals(underlyingAssetDecimals); + currentConfig.setDecimals(inputParams.underlyingAssetDecimals); currentConfig.setActive(true); currentConfig.setFrozen(false); - pool.setConfiguration(asset, currentConfig.data); + pool.setConfiguration(inputParams.underlyingAsset, currentConfig.data); emit ReserveInitialized( - asset, + inputParams.underlyingAsset, aTokenProxyAddress, stableDebtTokenProxyAddress, variableDebtTokenProxyAddress, - interestRateStrategyAddress + inputParams.interestRateStrategyAddress ); } /** * @dev Updates the aToken implementation for the reserve - * @param asset The address of the underlying asset of the reserve to be updated - * @param implementation The address of the new aToken implementation **/ - function updateAToken(address asset, address implementation) external onlyPoolAdmin { - DataTypes.ReserveData memory reserveData = pool.getReserveData(asset); + function updateAToken(UpdateATokenInput calldata inputParams) external onlyPoolAdmin { + ILendingPool cachedPool = pool; - _upgradeTokenImplementation(asset, reserveData.aTokenAddress, implementation); + DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(inputParams.asset); - emit ATokenUpgraded(asset, reserveData.aTokenAddress, implementation); + DataTypes.ReserveConfigurationMap memory configuration = + cachedPool.getConfiguration(inputParams.asset); + + (, , , uint256 decimals, ) = configuration.getParamsMemory(); + + _upgradeTokenImplementation( + reserveData.aTokenAddress, + inputParams.implementation, + abi.encodeWithSelector( + IInitializableAToken.initialize.selector, + cachedPool, + inputParams.treasury, + inputParams.asset, + inputParams.incentivesController, + decimals, + inputParams.name, + inputParams.symbol + ) + ); + + emit ATokenUpgraded(inputParams.asset, reserveData.aTokenAddress, inputParams.implementation); } /** * @dev Updates the stable debt token implementation for the reserve - * @param asset The address of the underlying asset of the reserve to be updated - * @param implementation The address of the new aToken implementation **/ - function updateStableDebtToken(address asset, address implementation) external onlyPoolAdmin { - DataTypes.ReserveData memory reserveData = pool.getReserveData(asset); + function updateStableDebtToken(UpdateDebtTokenInput calldata inputParams) external onlyPoolAdmin { + ILendingPool cachedPool = pool; - _upgradeTokenImplementation(asset, reserveData.stableDebtTokenAddress, implementation); + DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(inputParams.asset); - emit StableDebtTokenUpgraded(asset, reserveData.stableDebtTokenAddress, implementation); + DataTypes.ReserveConfigurationMap memory configuration = + cachedPool.getConfiguration(inputParams.asset); + + (, , , uint256 decimals, ) = configuration.getParamsMemory(); + + _upgradeTokenImplementation( + reserveData.stableDebtTokenAddress, + inputParams.implementation, + abi.encodeWithSelector( + IInitializableDebtToken.initialize.selector, + cachedPool, + inputParams.asset, + inputParams.incentivesController, + decimals, + inputParams.name, + inputParams.symbol + ) + ); + + emit StableDebtTokenUpgraded( + inputParams.asset, + reserveData.stableDebtTokenAddress, + inputParams.implementation + ); } /** * @dev Updates the variable debt token implementation for the asset - * @param asset The address of the underlying asset of the reserve to be updated - * @param implementation The address of the new aToken implementation **/ - function updateVariableDebtToken(address asset, address implementation) external onlyPoolAdmin { - DataTypes.ReserveData memory reserveData = pool.getReserveData(asset); + function updateVariableDebtToken(UpdateDebtTokenInput calldata inputParams) + external + onlyPoolAdmin + { + ILendingPool cachedPool = pool; - _upgradeTokenImplementation(asset, reserveData.variableDebtTokenAddress, implementation); + DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(inputParams.asset); - emit VariableDebtTokenUpgraded(asset, reserveData.variableDebtTokenAddress, implementation); + DataTypes.ReserveConfigurationMap memory configuration = + cachedPool.getConfiguration(inputParams.asset); + + (, , , uint256 decimals, ) = configuration.getParamsMemory(); + + _upgradeTokenImplementation( + reserveData.variableDebtTokenAddress, + inputParams.implementation, + abi.encodeWithSelector( + IInitializableDebtToken.initialize.selector, + cachedPool, + inputParams.asset, + inputParams.incentivesController, + decimals, + inputParams.name, + inputParams.symbol + ) + ); + + emit VariableDebtTokenUpgraded( + inputParams.asset, + reserveData.variableDebtTokenAddress, + inputParams.implementation + ); } /** @@ -509,44 +448,27 @@ contract LendingPoolConfigurator is VersionedInitializable { pool.setPause(val); } - function _initTokenWithProxy(address implementation, uint8 decimals) internal returns (address) { + function _initTokenWithProxy(address implementation, bytes memory initParams) + internal + returns (address) + { InitializableImmutableAdminUpgradeabilityProxy proxy = new InitializableImmutableAdminUpgradeabilityProxy(address(this)); - bytes memory params = - abi.encodeWithSignature( - 'initialize(uint8,string,string)', - decimals, - IERC20Detailed(implementation).name(), - IERC20Detailed(implementation).symbol() - ); - - proxy.initialize(implementation, params); + proxy.initialize(implementation, initParams); return address(proxy); } function _upgradeTokenImplementation( - address asset, address proxyAddress, - address implementation + address implementation, + bytes memory initParams ) internal { InitializableImmutableAdminUpgradeabilityProxy proxy = InitializableImmutableAdminUpgradeabilityProxy(payable(proxyAddress)); - DataTypes.ReserveConfigurationMap memory configuration = pool.getConfiguration(asset); - - (, , , uint256 decimals, ) = configuration.getParamsMemory(); - - bytes memory params = - abi.encodeWithSignature( - 'initialize(uint8,string,string)', - uint8(decimals), - IERC20Detailed(implementation).name(), - IERC20Detailed(implementation).symbol() - ); - - proxy.upgradeToAndCall(implementation, params); + proxy.upgradeToAndCall(implementation, initParams); } function _checkNoLiquidity(address asset) internal view { diff --git a/contracts/protocol/lendingpool/LendingPoolStorage.sol b/contracts/protocol/lendingpool/LendingPoolStorage.sol index 4edff4a3..198a3eea 100644 --- a/contracts/protocol/lendingpool/LendingPoolStorage.sol +++ b/contracts/protocol/lendingpool/LendingPoolStorage.sol @@ -23,4 +23,10 @@ contract LendingPoolStorage { uint256 internal _reservesCount; bool internal _paused; + + uint256 internal _maxStableRateBorrowSizePercent; + + uint256 internal _flashLoanPremiumTotal; + + uint256 internal _maxNumberOfReserves; } diff --git a/contracts/protocol/tokenization/AToken.sol b/contracts/protocol/tokenization/AToken.sol index 00df0b61..1a47ebf4 100644 --- a/contracts/protocol/tokenization/AToken.sol +++ b/contracts/protocol/tokenization/AToken.sol @@ -9,13 +9,18 @@ import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {Errors} from '../libraries/helpers/Errors.sol'; import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol'; import {IncentivizedERC20} from './IncentivizedERC20.sol'; +import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; /** * @title Aave ERC20 AToken * @dev Implementation of the interest bearing token for the Aave protocol * @author Aave */ -contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { +contract AToken is + VersionedInitializable, + IncentivizedERC20('ATOKEN_IMPL', 'ATOKEN_IMPL', 0), + IAToken +{ using WadRayMath for uint256; using SafeERC20 for IERC20; @@ -25,44 +30,46 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { bytes32 public constant PERMIT_TYPEHASH = keccak256('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)'); - uint256 public constant UINT_MAX_VALUE = uint256(-1); uint256 public constant ATOKEN_REVISION = 0x1; - address public immutable UNDERLYING_ASSET_ADDRESS; - address public immutable RESERVE_TREASURY_ADDRESS; - ILendingPool public immutable POOL; /// @dev owner => next valid nonce to submit with permit() mapping(address => uint256) public _nonces; bytes32 public DOMAIN_SEPARATOR; - modifier onlyLendingPool { - require(_msgSender() == address(POOL), Errors.CT_CALLER_MUST_BE_LENDING_POOL); - _; - } + ILendingPool internal _pool; + address internal _treasury; + address internal _underlyingAsset; + IAaveIncentivesController internal _incentivesController; - constructor( - ILendingPool pool, - address underlyingAssetAddress, - address reserveTreasuryAddress, - string memory tokenName, - string memory tokenSymbol, - address incentivesController - ) public IncentivizedERC20(tokenName, tokenSymbol, 18, incentivesController) { - POOL = pool; - UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress; - RESERVE_TREASURY_ADDRESS = reserveTreasuryAddress; + modifier onlyLendingPool { + require(_msgSender() == address(_pool), Errors.CT_CALLER_MUST_BE_LENDING_POOL); + _; } function getRevision() internal pure virtual override returns (uint256) { return ATOKEN_REVISION; } + /** + * @dev Initializes the aToken + * @param pool The address of the lending pool where this aToken will be used + * @param treasury The address of the Aave treasury, receiving the fees on this aToken + * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) + * @param incentivesController The smart contract managing potential incentives distribution + * @param aTokenDecimals The decimals of the aToken, same as the underlying asset's + * @param aTokenName The name of the aToken + * @param aTokenSymbol The symbol of the aToken + */ function initialize( - uint8 underlyingAssetDecimals, - string calldata tokenName, - string calldata tokenSymbol - ) external virtual initializer { + ILendingPool pool, + address treasury, + address underlyingAsset, + IAaveIncentivesController incentivesController, + uint8 aTokenDecimals, + string calldata aTokenName, + string calldata aTokenSymbol + ) external override initializer { uint256 chainId; //solium-disable-next-line @@ -73,16 +80,21 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { DOMAIN_SEPARATOR = keccak256( abi.encode( EIP712_DOMAIN, - keccak256(bytes(tokenName)), + keccak256(bytes(aTokenName)), keccak256(EIP712_REVISION), chainId, address(this) ) ); - _setName(tokenName); - _setSymbol(tokenSymbol); - _setDecimals(underlyingAssetDecimals); + _setName(aTokenName); + _setSymbol(aTokenSymbol); + _setDecimals(aTokenDecimals); + + _pool = pool; + _treasury = treasury; + _underlyingAsset = underlyingAsset; + _incentivesController = incentivesController; } /** @@ -103,7 +115,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { require(amountScaled != 0, Errors.CT_INVALID_BURN_AMOUNT); _burn(user, amountScaled); - IERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(receiverOfUnderlying, amount); + IERC20(_underlyingAsset).safeTransfer(receiverOfUnderlying, amount); emit Transfer(user, address(0), amount); emit Burn(user, receiverOfUnderlying, amount, index); @@ -145,14 +157,16 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { return; } + address treasury = _treasury; + // Compared to the normal mint, we don't check for rounding errors. // The amount to mint can easily be very small since it is a fraction of the interest ccrued. // In that case, the treasury will experience a (very small) loss, but it // wont cause potentially valid transactions to fail. - _mint(RESERVE_TREASURY_ADDRESS, amount.rayDiv(index)); + _mint(treasury, amount.rayDiv(index)); - emit Transfer(address(0), RESERVE_TREASURY_ADDRESS, amount); - emit Mint(RESERVE_TREASURY_ADDRESS, amount, index); + emit Transfer(address(0), treasury, amount); + emit Mint(treasury, amount, index); } /** @@ -185,7 +199,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { override(IncentivizedERC20, IERC20) returns (uint256) { - return super.balanceOf(user).rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS)); + return super.balanceOf(user).rayMul(_pool.getReserveNormalizedIncome(_underlyingAsset)); } /** @@ -226,7 +240,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { return 0; } - return currentSupplyScaled.rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS)); + return currentSupplyScaled.rayMul(_pool.getReserveNormalizedIncome(_underlyingAsset)); } /** @@ -237,6 +251,41 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { return super.totalSupply(); } + /** + * @dev Returns the address of the Aave treasury, receiving the fees on this aToken + **/ + function RESERVE_TREASURY_ADDRESS() public view returns (address) { + return _treasury; + } + + /** + * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) + **/ + function UNDERLYING_ASSET_ADDRESS() public view returns (address) { + return _underlyingAsset; + } + + /** + * @dev Returns the address of the lending pool where this aToken is used + **/ + function POOL() public view returns (ILendingPool) { + return _pool; + } + + /** + * @dev For internal usage in the logic of the parent contract IncentivizedERC20 + **/ + function _getIncentivesController() internal view override returns (IAaveIncentivesController) { + return _incentivesController; + } + + /** + * @dev Returns the address of the incentives controller contract + **/ + function getIncentivesController() external view override returns (IAaveIncentivesController) { + return _getIncentivesController(); + } + /** * @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer * assets in borrow(), withdraw() and flashLoan() @@ -250,7 +299,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { onlyLendingPool returns (uint256) { - IERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(target, amount); + IERC20(_underlyingAsset).safeTransfer(target, amount); return amount; } @@ -305,7 +354,10 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { uint256 amount, bool validate ) internal { - uint256 index = POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS); + address underlyingAsset = _underlyingAsset; + ILendingPool pool = _pool; + + uint256 index = pool.getReserveNormalizedIncome(underlyingAsset); uint256 fromBalanceBefore = super.balanceOf(from).rayMul(index); uint256 toBalanceBefore = super.balanceOf(to).rayMul(index); @@ -313,14 +365,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { super._transfer(from, to, amount.rayDiv(index)); if (validate) { - POOL.finalizeTransfer( - UNDERLYING_ASSET_ADDRESS, - from, - to, - amount, - fromBalanceBefore, - toBalanceBefore - ); + pool.finalizeTransfer(underlyingAsset, from, to, amount, fromBalanceBefore, toBalanceBefore); } emit BalanceTransfer(from, to, amount, index); diff --git a/contracts/protocol/tokenization/DelegationAwareAToken.sol b/contracts/protocol/tokenization/DelegationAwareAToken.sol index 4e49f2b6..443e10fb 100644 --- a/contracts/protocol/tokenization/DelegationAwareAToken.sol +++ b/contracts/protocol/tokenization/DelegationAwareAToken.sol @@ -14,36 +14,17 @@ import {AToken} from './AToken.sol'; contract DelegationAwareAToken is AToken { modifier onlyPoolAdmin { require( - _msgSender() == ILendingPool(POOL).getAddressesProvider().getPoolAdmin(), + _msgSender() == ILendingPool(_pool).getAddressesProvider().getPoolAdmin(), Errors.CALLER_NOT_POOL_ADMIN ); _; } - constructor( - ILendingPool pool, - address underlyingAssetAddress, - address reserveTreasury, - string memory tokenName, - string memory tokenSymbol, - address incentivesController - ) - public - AToken( - pool, - underlyingAssetAddress, - reserveTreasury, - tokenName, - tokenSymbol, - incentivesController - ) - {} - /** * @dev Delegates voting power of the underlying asset to a `delegatee` address * @param delegatee The address that will receive the delegation **/ function delegateUnderlyingTo(address delegatee) external onlyPoolAdmin { - IDelegationToken(UNDERLYING_ASSET_ADDRESS).delegate(delegatee); + IDelegationToken(_underlyingAsset).delegate(delegatee); } } diff --git a/contracts/protocol/tokenization/IncentivizedERC20.sol b/contracts/protocol/tokenization/IncentivizedERC20.sol index 101eaf9a..fb831769 100644 --- a/contracts/protocol/tokenization/IncentivizedERC20.sol +++ b/contracts/protocol/tokenization/IncentivizedERC20.sol @@ -12,11 +12,9 @@ import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesControl * @notice Basic ERC20 implementation * @author Aave, inspired by the Openzeppelin ERC20 implementation **/ -contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { +abstract contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { using SafeMath for uint256; - IAaveIncentivesController internal immutable _incentivesController; - mapping(address => uint256) internal _balances; mapping(address => mapping(address => uint256)) private _allowances; @@ -28,13 +26,11 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { constructor( string memory name, string memory symbol, - uint8 decimals, - address incentivesController + uint8 decimals ) public { _name = name; _symbol = symbol; _decimals = decimals; - _incentivesController = IAaveIncentivesController(incentivesController); } /** @@ -72,6 +68,12 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { return _balances[account]; } + /** + * @return Abstract function implemented by the child aToken/debtToken. + * Done this way in order to not break compatibility with previous versions of aTokens/debtTokens + **/ + function _getIncentivesController() internal view virtual returns(IAaveIncentivesController); + /** * @dev Executes a transfer of tokens from _msgSender() to recipient * @param recipient The recipient of the tokens @@ -180,11 +182,11 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { uint256 oldRecipientBalance = _balances[recipient]; _balances[recipient] = _balances[recipient].add(amount); - if (address(_incentivesController) != address(0)) { + if (address(_getIncentivesController()) != address(0)) { uint256 currentTotalSupply = _totalSupply; - _incentivesController.handleAction(sender, currentTotalSupply, oldSenderBalance); + _getIncentivesController().handleAction(sender, currentTotalSupply, oldSenderBalance); if (sender != recipient) { - _incentivesController.handleAction(recipient, currentTotalSupply, oldRecipientBalance); + _getIncentivesController().handleAction(recipient, currentTotalSupply, oldRecipientBalance); } } } @@ -200,8 +202,8 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { uint256 oldAccountBalance = _balances[account]; _balances[account] = oldAccountBalance.add(amount); - if (address(_incentivesController) != address(0)) { - _incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance); + if (address(_getIncentivesController()) != address(0)) { + _getIncentivesController().handleAction(account, oldTotalSupply, oldAccountBalance); } } @@ -216,8 +218,8 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { uint256 oldAccountBalance = _balances[account]; _balances[account] = oldAccountBalance.sub(amount, 'ERC20: burn amount exceeds balance'); - if (address(_incentivesController) != address(0)) { - _incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance); + if (address(_getIncentivesController()) != address(0)) { + _getIncentivesController().handleAction(account, oldTotalSupply, oldAccountBalance); } } diff --git a/contracts/protocol/tokenization/StableDebtToken.sol b/contracts/protocol/tokenization/StableDebtToken.sol index 78401405..f52c4931 100644 --- a/contracts/protocol/tokenization/StableDebtToken.sol +++ b/contracts/protocol/tokenization/StableDebtToken.sol @@ -5,6 +5,8 @@ import {DebtTokenBase} from './base/DebtTokenBase.sol'; import {MathUtils} from '../libraries/math/MathUtils.sol'; import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {IStableDebtToken} from '../../interfaces/IStableDebtToken.sol'; +import {ILendingPool} from '../../interfaces/ILendingPool.sol'; +import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; import {Errors} from '../libraries/helpers/Errors.sol'; /** @@ -23,13 +25,35 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { mapping(address => uint256) internal _usersStableRate; uint40 internal _totalSupplyTimestamp; - constructor( - address pool, + ILendingPool internal _pool; + address internal _underlyingAsset; + IAaveIncentivesController internal _incentivesController; + + /** + * @dev Initializes the debt token. + * @param pool The address of the lending pool where this aToken will be used + * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) + * @param incentivesController The smart contract managing potential incentives distribution + * @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's + * @param debtTokenName The name of the token + * @param debtTokenSymbol The symbol of the token + */ + function initialize( + ILendingPool pool, address underlyingAsset, - string memory name, - string memory symbol, - address incentivesController - ) public DebtTokenBase(pool, underlyingAsset, name, symbol, incentivesController) {} + IAaveIncentivesController incentivesController, + uint8 debtTokenDecimals, + string memory debtTokenName, + string memory debtTokenSymbol + ) public override initializer { + _setName(debtTokenName); + _setSymbol(debtTokenSymbol); + _setDecimals(debtTokenDecimals); + + _pool = pool; + _underlyingAsset = underlyingAsset; + _incentivesController = incentivesController; + } /** * @dev Gets the revision of the stable debt token implementation @@ -300,6 +324,48 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { return super.balanceOf(user); } + /** + * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) + **/ + function UNDERLYING_ASSET_ADDRESS() public view returns (address) { + return _underlyingAsset; + } + + /** + * @dev Returns the address of the lending pool where this aToken is used + **/ + function POOL() public view returns (ILendingPool) { + return _pool; + } + + /** + * @dev Returns the address of the incentives controller contract + **/ + function getIncentivesController() external view override returns (IAaveIncentivesController) { + return _getIncentivesController(); + } + + /** + * @dev For internal usage in the logic of the parent contracts + **/ + function _getIncentivesController() internal view override returns (IAaveIncentivesController) { + return _incentivesController; + } + + /** + * @dev For internal usage in the logic of the parent contracts + **/ + function _getUnderlyingAssetAddress() internal view override returns (address) { + return _underlyingAsset; + } + + /** + * @dev For internal usage in the logic of the parent contracts + **/ + function _getLendingPool() internal view override returns (ILendingPool) { + return _pool; + } + /** * @dev Calculates the total supply * @param avgRate The average rate at which the total supply increases diff --git a/contracts/protocol/tokenization/VariableDebtToken.sol b/contracts/protocol/tokenization/VariableDebtToken.sol index d2e27ac3..60a47e12 100644 --- a/contracts/protocol/tokenization/VariableDebtToken.sol +++ b/contracts/protocol/tokenization/VariableDebtToken.sol @@ -5,6 +5,8 @@ import {IVariableDebtToken} from '../../interfaces/IVariableDebtToken.sol'; import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {Errors} from '../libraries/helpers/Errors.sol'; import {DebtTokenBase} from './base/DebtTokenBase.sol'; +import {ILendingPool} from '../../interfaces/ILendingPool.sol'; +import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; /** * @title VariableDebtToken @@ -17,13 +19,35 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { uint256 public constant DEBT_TOKEN_REVISION = 0x1; - constructor( - address pool, + ILendingPool internal _pool; + address internal _underlyingAsset; + IAaveIncentivesController internal _incentivesController; + + /** + * @dev Initializes the debt token. + * @param pool The address of the lending pool where this aToken will be used + * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) + * @param incentivesController The smart contract managing potential incentives distribution + * @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's + * @param debtTokenName The name of the token + * @param debtTokenSymbol The symbol of the token + */ + function initialize( + ILendingPool pool, address underlyingAsset, - string memory name, - string memory symbol, - address incentivesController - ) public DebtTokenBase(pool, underlyingAsset, name, symbol, incentivesController) {} + IAaveIncentivesController incentivesController, + uint8 debtTokenDecimals, + string memory debtTokenName, + string memory debtTokenSymbol + ) public override initializer { + _setName(debtTokenName); + _setSymbol(debtTokenSymbol); + _setDecimals(debtTokenDecimals); + + _pool = pool; + _underlyingAsset = underlyingAsset; + _incentivesController = incentivesController; + } /** * @dev Gets the revision of the stable debt token implementation @@ -44,7 +68,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { return 0; } - return scaledBalance.rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS)); + return scaledBalance.rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAsset)); } /** @@ -113,8 +137,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { * @return The total supply **/ function totalSupply() public view virtual override returns (uint256) { - return - super.totalSupply().rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS)); + return super.totalSupply().rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAsset)); } /** @@ -139,4 +162,37 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { { return (super.balanceOf(user), super.totalSupply()); } + + /** + * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) + **/ + function UNDERLYING_ASSET_ADDRESS() public view returns (address) { + return _underlyingAsset; + } + + /** + * @dev Returns the address of the incentives controller contract + **/ + function getIncentivesController() external view override returns (IAaveIncentivesController) { + return _getIncentivesController(); + } + + /** + * @dev Returns the address of the lending pool where this aToken is used + **/ + function POOL() public view returns (ILendingPool) { + return _pool; + } + + function _getIncentivesController() internal view override returns (IAaveIncentivesController) { + return _incentivesController; + } + + function _getUnderlyingAssetAddress() internal view override returns (address) { + return _underlyingAsset; + } + + function _getLendingPool() internal view override returns (ILendingPool) { + return _pool; + } } diff --git a/contracts/protocol/tokenization/base/DebtTokenBase.sol b/contracts/protocol/tokenization/base/DebtTokenBase.sol index 07bdef22..4d75bc2f 100644 --- a/contracts/protocol/tokenization/base/DebtTokenBase.sol +++ b/contracts/protocol/tokenization/base/DebtTokenBase.sol @@ -16,54 +16,20 @@ import {Errors} from '../../libraries/helpers/Errors.sol'; */ abstract contract DebtTokenBase is - IncentivizedERC20, + IncentivizedERC20('DEBTTOKEN_IMPL', 'DEBTTOKEN_IMPL', 0), VersionedInitializable, ICreditDelegationToken { - address public immutable UNDERLYING_ASSET_ADDRESS; - ILendingPool public immutable POOL; - mapping(address => mapping(address => uint256)) internal _borrowAllowances; /** * @dev Only lending pool can call functions marked by this modifier **/ modifier onlyLendingPool { - require(_msgSender() == address(POOL), Errors.CT_CALLER_MUST_BE_LENDING_POOL); + require(_msgSender() == address(_getLendingPool()), Errors.CT_CALLER_MUST_BE_LENDING_POOL); _; } - /** - * @dev The metadata of the token will be set on the proxy, that the reason of - * passing "NULL" and 0 as metadata - */ - constructor( - address pool, - address underlyingAssetAddress, - string memory name, - string memory symbol, - address incentivesController - ) public IncentivizedERC20(name, symbol, 18, incentivesController) { - POOL = ILendingPool(pool); - UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress; - } - - /** - * @dev Initializes the debt token. - * @param name The name of the token - * @param symbol The symbol of the token - * @param decimals The decimals of the token - */ - function initialize( - uint8 decimals, - string memory name, - string memory symbol - ) public initializer { - _setName(name); - _setSymbol(symbol); - _setDecimals(decimals); - } - /** * @dev delegates borrowing power to a user on the specific debt token * @param delegatee the address receiving the delegated borrowing power @@ -73,7 +39,7 @@ abstract contract DebtTokenBase is **/ function approveDelegation(address delegatee, uint256 amount) external override { _borrowAllowances[_msgSender()][delegatee] = amount; - emit BorrowAllowanceDelegated(_msgSender(), delegatee, UNDERLYING_ASSET_ADDRESS, amount); + emit BorrowAllowanceDelegated(_msgSender(), delegatee, _getUnderlyingAssetAddress(), amount); } /** @@ -162,6 +128,10 @@ abstract contract DebtTokenBase is _borrowAllowances[delegator][delegatee] = newAllowance; - emit BorrowAllowanceDelegated(delegator, delegatee, UNDERLYING_ASSET_ADDRESS, newAllowance); + emit BorrowAllowanceDelegated(delegator, delegatee, _getUnderlyingAssetAddress(), newAllowance); } + + function _getUnderlyingAssetAddress() internal view virtual returns (address); + + function _getLendingPool() internal view virtual returns (ILendingPool); } From 5146efbaec429ad453e72526fe258a6fc4fda7f1 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 28 Jan 2021 22:06:09 -0500 Subject: [PATCH 048/219] Added agreed upon market parameters --- markets/uniswap/reservesConfigs.ts | 58 +++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/markets/uniswap/reservesConfigs.ts b/markets/uniswap/reservesConfigs.ts index 84ab8317..acd09475 100644 --- a/markets/uniswap/reservesConfigs.ts +++ b/markets/uniswap/reservesConfigs.ts @@ -23,7 +23,7 @@ export const strategyWBTC: IReserveParams = { 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(), + variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(), stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(), stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(), baseLTVAsCollateral: '7000', @@ -97,11 +97,11 @@ export const strategyDAIWETH: IReserveParams = { baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '500' }; export const strategyWBTCWETH: IReserveParams = { @@ -114,11 +114,11 @@ export const strategyWBTCWETH: IReserveParams = { baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '1500' }; export const strategyAAVEWETH: IReserveParams = { @@ -131,11 +131,11 @@ export const strategyAAVEWETH: IReserveParams = { baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '500' }; export const strategyBATWETH: IReserveParams = { @@ -148,11 +148,11 @@ export const strategyBATWETH: IReserveParams = { baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '1500' }; export const strategyUSDCDAI: IReserveParams = { @@ -165,11 +165,11 @@ export const strategyUSDCDAI: IReserveParams = { baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '1000' }; export const strategyCRVWETH: IReserveParams = { @@ -182,11 +182,11 @@ export const strategyCRVWETH: IReserveParams = { baseLTVAsCollateral: '5000', liquidationThreshold: '6000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '500' }; export const strategyLINKWETH: IReserveParams = { @@ -199,11 +199,11 @@ export const strategyLINKWETH: IReserveParams = { baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '1500' }; export const strategyMKRWETH: IReserveParams = { @@ -216,11 +216,11 @@ export const strategyMKRWETH: IReserveParams = { baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '1500' }; export const strategyRENWETH: IReserveParams = { @@ -233,11 +233,11 @@ export const strategyRENWETH: IReserveParams = { baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '1500' }; export const strategySNXWETH: IReserveParams = { @@ -250,11 +250,11 @@ export const strategySNXWETH: IReserveParams = { baseLTVAsCollateral: '4000', liquidationThreshold: '6000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '2000' }; export const strategyUNIWETH: IReserveParams = { @@ -267,11 +267,11 @@ export const strategyUNIWETH: IReserveParams = { baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '1500' }; export const strategyUSDCWETH: IReserveParams = { @@ -284,11 +284,11 @@ export const strategyUSDCWETH: IReserveParams = { baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '1000' }; export const strategyWBTCUSDC: IReserveParams = { @@ -301,11 +301,11 @@ export const strategyWBTCUSDC: IReserveParams = { baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '1500' }; export const strategyYFIWETH: IReserveParams = { @@ -318,9 +318,9 @@ export const strategyYFIWETH: IReserveParams = { baseLTVAsCollateral: '5000', liquidationThreshold: '6000', liquidationBonus: '11500', - borrowingEnabled: false, + borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '1500' }; \ No newline at end of file From 37ac8b5297b89c485fdbffdf8703b246cfcaa9ad Mon Sep 17 00:00:00 2001 From: David Racero Date: Fri, 29 Jan 2021 18:09:06 +0100 Subject: [PATCH 049/219] Add new edge case when flash liquidation same asset. Add tests. --- .../adapters/FlashLiquidationAdapter.sol | 74 +++-- package-lock.json | 4 +- test/uniswapAdapters.flashLiquidation.spec.ts | 257 ++++++++++++++---- 3 files changed, 252 insertions(+), 83 deletions(-) diff --git a/contracts/adapters/FlashLiquidationAdapter.sol b/contracts/adapters/FlashLiquidationAdapter.sol index 459c038e..1f329e0a 100644 --- a/contracts/adapters/FlashLiquidationAdapter.sol +++ b/contracts/adapters/FlashLiquidationAdapter.sol @@ -23,13 +23,15 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { struct LiquidationParams { address collateralAsset; - address debtAsset; + address borrowedAsset; address user; uint256 debtToCover; bool useEthPath; } struct LiquidationCallLocalVars { + uint256 initFlashBorrowedBalance; + uint256 diffFlashBorrowedBalance; uint256 initCollateralBalance; uint256 diffCollateralBalance; uint256 flashLoanDebt; @@ -53,10 +55,10 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { * @param initiator Address of the caller * @param params Additional variadic field to include extra params. Expected parameters: * address collateralAsset The collateral asset to release and will be exchanged to pay the flash loan premium - * address debtAsset The asset that must be covered + * address borrowedAsset The asset that must be covered * address user The user address with a Health Factor below 1 * uint256 debtToCover The amount of debt to cover - * bool useEthPath Use WETH as connector path between the collateralAsset and debtAsset at Uniswap + * bool useEthPath Use WETH as connector path between the collateralAsset and borrowedAsset at Uniswap */ function executeOperation( address[] calldata assets, @@ -69,11 +71,11 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { LiquidationParams memory decodedParams = _decodeParams(params); - require(assets.length == 1 && assets[0] == decodedParams.debtAsset, 'INCONSISTENT_PARAMS'); + require(assets.length == 1 && assets[0] == decodedParams.borrowedAsset, 'INCONSISTENT_PARAMS'); _liquidateAndSwap( decodedParams.collateralAsset, - decodedParams.debtAsset, + decodedParams.borrowedAsset, decodedParams.user, decodedParams.debtToCover, decodedParams.useEthPath, @@ -88,52 +90,64 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { /** * @dev * @param collateralAsset The collateral asset to release and will be exchanged to pay the flash loan premium - * @param debtAsset The asset that must be covered + * @param borrowedAsset The asset that must be covered * @param user The user address with a Health Factor below 1 * @param debtToCover The amount of debt to coverage, can be max(-1) to liquidate all possible debt * @param useEthPath true if the swap needs to occur using ETH in the routing, false otherwise - * @param coverAmount Amount of asset requested at the flash loan to liquidate the user position + * @param flashBorrowedAmount Amount of asset requested at the flash loan to liquidate the user position * @param premium Fee of the requested flash loan * @param initiator Address of the caller */ function _liquidateAndSwap( address collateralAsset, - address debtAsset, + address borrowedAsset, address user, uint256 debtToCover, bool useEthPath, - uint256 coverAmount, + uint256 flashBorrowedAmount, // 1000 uint256 premium, address initiator ) internal { LiquidationCallLocalVars memory vars; vars.initCollateralBalance = IERC20(collateralAsset).balanceOf(address(this)); - vars.flashLoanDebt = coverAmount.add(premium); + if (collateralAsset != borrowedAsset) { + vars.initFlashBorrowedBalance = IERC20(borrowedAsset).balanceOf(address(this)); + } + vars.flashLoanDebt = flashBorrowedAmount.add(premium); // 1010 // Approve LendingPool to use debt token for liquidation - IERC20(debtAsset).approve(address(LENDING_POOL), debtToCover); + IERC20(borrowedAsset).approve(address(LENDING_POOL), debtToCover); // Liquidate the user position and release the underlying collateral - LENDING_POOL.liquidationCall(collateralAsset, debtAsset, user, debtToCover, false); + LENDING_POOL.liquidationCall(collateralAsset, borrowedAsset, user, debtToCover, false); // Discover the liquidated tokens - vars.diffCollateralBalance = IERC20(collateralAsset).balanceOf(address(this)).sub( - vars.initCollateralBalance - ); + uint256 collateralBalanceAfter = IERC20(collateralAsset).balanceOf(address(this)); - // Swap released collateral into the debt asset, to repay the flash loan - vars.soldAmount = _swapTokensForExactTokens( - collateralAsset, - debtAsset, - vars.diffCollateralBalance, - vars.flashLoanDebt, - useEthPath - ); + vars.diffCollateralBalance = collateralBalanceAfter.sub(vars.initCollateralBalance); + + if (collateralAsset != borrowedAsset) { + // Discover flash loan balance + uint256 flashBorrowedAssetAfter = IERC20(borrowedAsset).balanceOf(address(this)); + + vars.diffFlashBorrowedBalance = flashBorrowedAssetAfter.sub( + vars.initFlashBorrowedBalance.sub(flashBorrowedAmount) + ); + // Swap released collateral into the debt asset, to repay the flash loan + vars.soldAmount = _swapTokensForExactTokens( + collateralAsset, + borrowedAsset, + vars.diffCollateralBalance, + vars.flashLoanDebt.sub(vars.diffFlashBorrowedBalance), + useEthPath + ); + vars.remainingTokens = vars.diffCollateralBalance.sub(vars.soldAmount); + } else { + vars.remainingTokens = vars.diffCollateralBalance.sub(premium); + } // Allow repay of flash loan - IERC20(debtAsset).approve(address(LENDING_POOL), vars.flashLoanDebt); - - vars.remainingTokens = vars.diffCollateralBalance.sub(vars.soldAmount); + IERC20(borrowedAsset).approve(address(LENDING_POOL), vars.flashLoanDebt); // Transfer remaining tokens to initiator if (vars.remainingTokens > 0) { @@ -145,21 +159,21 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { * @dev Decodes the information encoded in the flash loan params * @param params Additional variadic field to include extra params. Expected parameters: * address collateralAsset The collateral asset to claim - * address debtAsset The asset that must be covered and will be exchanged to pay the flash loan premium + * address borrowedAsset The asset that must be covered and will be exchanged to pay the flash loan premium * address user The user address with a Health Factor below 1 * uint256 debtToCover The amount of debt to cover - * bool useEthPath Use WETH as connector path between the collateralAsset and debtAsset at Uniswap + * bool useEthPath Use WETH as connector path between the collateralAsset and borrowedAsset at Uniswap * @return LiquidationParams struct containing decoded params */ function _decodeParams(bytes memory params) internal pure returns (LiquidationParams memory) { ( address collateralAsset, - address debtAsset, + address borrowedAsset, address user, uint256 debtToCover, bool useEthPath ) = abi.decode(params, (address, address, address, uint256, bool)); - return LiquidationParams(collateralAsset, debtAsset, user, debtToCover, useEthPath); + return LiquidationParams(collateralAsset, borrowedAsset, user, debtToCover, useEthPath); } } diff --git a/package-lock.json b/package-lock.json index dfdeb1a5..3ae83800 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { - "name": "protocol-v2", - "version": "1.0.0", + "name": "@aave/protocol-v2", + "version": "1.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/test/uniswapAdapters.flashLiquidation.spec.ts b/test/uniswapAdapters.flashLiquidation.spec.ts index ab5a0bd1..063c6930 100644 --- a/test/uniswapAdapters.flashLiquidation.spec.ts +++ b/test/uniswapAdapters.flashLiquidation.spec.ts @@ -7,7 +7,7 @@ import { getMockUniswapRouter } from '../helpers/contracts-getters'; import { deployFlashLiquidationAdapter } from '../helpers/contracts-deployments'; import { MockUniswapV2Router02 } from '../types/MockUniswapV2Router02'; import BigNumber from 'bignumber.js'; -import { DRE, evmRevert, evmSnapshot, increaseTime } from '../helpers/misc-utils'; +import { DRE, evmRevert, evmSnapshot, increaseTime, waitForTx } from '../helpers/misc-utils'; import { ethers } from 'ethers'; import { ProtocolErrors, RateMode } from '../helpers/types'; import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, oneEther } from '../helpers/constants'; @@ -91,6 +91,84 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { ); }; + const depositSameAssetAndHFBelowOne = async () => { + const { dai, weth, users, pool, oracle } = testEnv; + const depositor = users[0]; + const borrower = users[1]; + + //mints DAI to depositor + await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access depositor wallet + await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 1 deposits 1000 DAI + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); + //user 2 deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); + + //approve protocol to access the borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 2 borrows + + const userGlobalDataBefore = await pool.getUserAccountData(borrower.address); + const daiPrice = await oracle.getAssetPrice(dai.address); + + const amountDAIToBorrow = await convertToCurrencyDecimals( + dai.address, + new BigNumber(userGlobalDataBefore.availableBorrowsETH.toString()) + .div(daiPrice.toString()) + .multipliedBy(0.8) + .toFixed(0) + ); + await waitForTx( + await pool + .connect(borrower.signer) + .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address) + ); + + const userGlobalDataBefore2 = await pool.getUserAccountData(borrower.address); + + const amountWETHToBorrow = new BigNumber(userGlobalDataBefore2.availableBorrowsETH.toString()) + .multipliedBy(0.8) + .toFixed(0); + + await pool + .connect(borrower.signer) + .borrow(weth.address, amountWETHToBorrow, RateMode.Variable, '0', borrower.address); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.equal( + '8250', + INVALID_HF + ); + + await oracle.setAssetPrice( + dai.address, + new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0) + ); + + const userGlobalData = await pool.getUserAccountData(borrower.address); + + expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( + oneEther.toFixed(0), + INVALID_HF + ); + }; + beforeEach(async () => { evmSnapshotId = await evmSnapshot(); }); @@ -212,22 +290,10 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { ); // Expect Swapped event - await expect(Promise.resolve(tx)) - .to.emit(flashLiquidationAdapter, 'Swapped') - .withArgs(weth.address, dai.address, expectedSwap.toString(), flashLoanDebt); + await expect(Promise.resolve(tx)).to.emit(flashLiquidationAdapter, 'Swapped'); // Expect LiquidationCall event - await expect(Promise.resolve(tx)) - .to.emit(pool, 'LiquidationCall') - .withArgs( - weth.address, - dai.address, - borrower.address, - amountToLiquidate.toString(), - expectedCollateralLiquidated.toString(), - flashLiquidationAdapter.address, - false - ); + await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); const userReserveDataAfter = await getUserData( pool, @@ -255,6 +321,20 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { txTimestamp ); + const collateralAssetContractBalance = await weth.balanceOf( + flashLiquidationAdapter.address + ); + const borrowAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); + + expect(collateralAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); + expect(borrowAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); + expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), 'Invalid user debt after liquidation' @@ -294,6 +374,87 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { }); }); + describe('executeOperation: succesfully liquidateCall with same asset via Flash Loan, but no swap needed', () => { + it('Liquidates the borrow with profit', async () => { + await depositSameAssetAndHFBelowOne(); + await increaseTime(100); + + const { weth, users, pool, oracle, helpersContract, flashLiquidationAdapter } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + + const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); + + const assetPrice = await oracle.getAssetPrice(weth.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + weth.address, + borrower.address + ); + + const assetDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const amountToLiquidate = userReserveDataBefore.currentVariableDebt.div(2).toFixed(0); + + const expectedCollateralLiquidated = new BigNumber(assetPrice.toString()) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(assetDecimals)) + .div(new BigNumber(assetPrice.toString()).times(new BigNumber(10).pow(assetDecimals))) + .div(100) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) + .multipliedBy(1.0009) + .toFixed(0); + + const params = buildFlashLiquidationAdapterParams( + weth.address, + weth.address, + borrower.address, + amountToLiquidate, + false + ); + const tx = await pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [weth.address], + [amountToLiquidate], + [0], + borrower.address, + params, + 0 + ); + + // Dont expect Swapped event due is same asset + await expect(Promise.resolve(tx)).to.not.emit(flashLiquidationAdapter, 'Swapped'); + + // Expect LiquidationCall event + await expect(Promise.resolve(tx)) + .to.emit(pool, 'LiquidationCall') + .withArgs( + weth.address, + weth.address, + borrower.address, + amountToLiquidate.toString(), + expectedCollateralLiquidated.toString(), + flashLiquidationAdapter.address, + false + ); + + const borrowAssetContractBalance = await weth.balanceOf(flashLiquidationAdapter.address); + + expect(borrowAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); + }); + }); + describe('executeOperation: succesfully liquidateCall and swap via Flash Loan without profits', () => { it('Liquidates the borrow', async () => { await depositAndHFBelowOne(); @@ -367,7 +528,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { .flashLoan( flashLiquidationAdapter.address, [dai.address], - [amountToLiquidate], + [flashLoanDebt], [0], borrower.address, params, @@ -375,27 +536,10 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { ); // Expect Swapped event - await expect(Promise.resolve(tx)) - .to.emit(flashLiquidationAdapter, 'Swapped') - .withArgs( - weth.address, - dai.address, - expectedCollateralLiquidated.toString(), - flashLoanDebt - ); + await expect(Promise.resolve(tx)).to.emit(flashLiquidationAdapter, 'Swapped'); // Expect LiquidationCall event - await expect(Promise.resolve(tx)) - .to.emit(pool, 'LiquidationCall') - .withArgs( - weth.address, - dai.address, - borrower.address, - amountToLiquidate.toString(), - expectedCollateralLiquidated.toString(), - flashLiquidationAdapter.address, - false - ); + await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); const userReserveDataAfter = await getUserData( pool, @@ -423,6 +567,17 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { txTimestamp ); + const collateralAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); + const borrowAssetContractBalance = await weth.balanceOf(flashLiquidationAdapter.address); + + expect(collateralAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); + expect(borrowAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), 'Invalid user debt after liquidation' @@ -440,13 +595,6 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { 'Invalid liquidity APY' ); - expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(daiReserveDataBefore.availableLiquidity.toString()) - .plus(flashLoanDebt) - .toFixed(0), - 'Invalid principal available liquidity' - ); - expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) .minus(expectedCollateralLiquidated) @@ -512,7 +660,9 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { .div(100) .decimalPlaces(0, BigNumber.ROUND_DOWN); - const flashLoanDebt = new BigNumber(extraAmount.toString()).multipliedBy(1.0009).toFixed(0); + const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) + .multipliedBy(1.0009) + .toFixed(0); // Set how much ETH will be sold and swapped for DAI at Uniswap mock await ( @@ -542,17 +692,22 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { ); // Expect Swapped event - await expect(Promise.resolve(tx)) - .to.emit(flashLiquidationAdapter, 'Swapped') - .withArgs( - weth.address, - dai.address, - expectedCollateralLiquidated.toString(), - flashLoanDebt - ); + await expect(Promise.resolve(tx)).to.emit(flashLiquidationAdapter, 'Swapped'); // Expect LiquidationCall event await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); + + const collateralAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); + const borrowAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); + + expect(collateralAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); + expect(borrowAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); }); }); From b4d72bfc374cf23dc93f8d01174a89709a2816f9 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 29 Jan 2021 22:51:59 -0500 Subject: [PATCH 050/219] Pulled contracts for light deployment --- contracts/adapters/BaseUniswapAdapter.sol | 534 ++++++++++++++++++ .../adapters/UniswapLiquiditySwapAdapter.sol | 280 +++++++++ contracts/adapters/UniswapRepayAdapter.sol | 259 +++++++++ .../interfaces/IBaseUniswapAdapter.sol | 90 +++ .../deployments/ATokensAndRatesHelper.sol | 103 ++-- .../StableAndVariableTokensHelper.sol | 27 +- contracts/interfaces/IAToken.sol | 9 +- contracts/interfaces/IERC20WithPermit.sol | 16 + contracts/interfaces/IInitializableAToken.sol | 32 ++ .../interfaces/IInitializableDebtToken.sol | 30 + .../interfaces/ILendingPoolConfigurator.sol | 176 ++++++ contracts/interfaces/IStableDebtToken.sol | 10 +- contracts/interfaces/IUniswapV2Router02.sol | 24 + contracts/interfaces/IVariableDebtToken.sol | 9 +- .../mocks/swap/MockUniswapV2Router02.sol | 106 ++++ contracts/mocks/upgradeability/MockAToken.sol | 32 +- .../upgradeability/MockStableDebtToken.sol | 11 - .../upgradeability/MockVariableDebtToken.sol | 17 - .../protocol/lendingpool/LendingPool.sol | 46 +- .../lendingpool/LendingPoolConfigurator.sol | 374 +++++------- .../lendingpool/LendingPoolStorage.sol | 6 + .../libraries/logic/ValidationLogic.sol | 9 +- contracts/protocol/tokenization/AToken.sol | 133 +++-- .../tokenization/DelegationAwareAToken.sol | 23 +- .../tokenization/IncentivizedERC20.sol | 28 +- .../protocol/tokenization/StableDebtToken.sol | 78 ++- .../tokenization/VariableDebtToken.sol | 74 ++- .../tokenization/base/DebtTokenBase.sol | 46 +- 28 files changed, 2051 insertions(+), 531 deletions(-) create mode 100644 contracts/adapters/BaseUniswapAdapter.sol create mode 100644 contracts/adapters/UniswapLiquiditySwapAdapter.sol create mode 100644 contracts/adapters/UniswapRepayAdapter.sol create mode 100644 contracts/adapters/interfaces/IBaseUniswapAdapter.sol create mode 100644 contracts/interfaces/IERC20WithPermit.sol create mode 100644 contracts/interfaces/IInitializableAToken.sol create mode 100644 contracts/interfaces/IInitializableDebtToken.sol create mode 100644 contracts/interfaces/ILendingPoolConfigurator.sol create mode 100644 contracts/interfaces/IUniswapV2Router02.sol create mode 100644 contracts/mocks/swap/MockUniswapV2Router02.sol diff --git a/contracts/adapters/BaseUniswapAdapter.sol b/contracts/adapters/BaseUniswapAdapter.sol new file mode 100644 index 00000000..b04bc8a1 --- /dev/null +++ b/contracts/adapters/BaseUniswapAdapter.sol @@ -0,0 +1,534 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {PercentageMath} from '../protocol/libraries/math/PercentageMath.sol'; +import {SafeMath} from '../dependencies/openzeppelin/contracts/SafeMath.sol'; +import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; +import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; +import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol'; +import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol'; +import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; +import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; +import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol'; +import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol'; +import {IERC20WithPermit} from '../interfaces/IERC20WithPermit.sol'; +import {FlashLoanReceiverBase} from '../flashloan/base/FlashLoanReceiverBase.sol'; +import {IBaseUniswapAdapter} from './interfaces/IBaseUniswapAdapter.sol'; + +/** + * @title BaseUniswapAdapter + * @notice Implements the logic for performing assets swaps in Uniswap V2 + * @author Aave + **/ +abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapter, Ownable { + using SafeMath for uint256; + using PercentageMath for uint256; + using SafeERC20 for IERC20; + + // Max slippage percent allowed + uint256 public constant override MAX_SLIPPAGE_PERCENT = 3000; // 30% + // FLash Loan fee set in lending pool + uint256 public constant override FLASHLOAN_PREMIUM_TOTAL = 9; + // USD oracle asset address + address public constant override USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96; + + address public immutable override WETH_ADDRESS; + IPriceOracleGetter public immutable override ORACLE; + IUniswapV2Router02 public immutable override UNISWAP_ROUTER; + + constructor( + ILendingPoolAddressesProvider addressesProvider, + IUniswapV2Router02 uniswapRouter, + address wethAddress + ) public FlashLoanReceiverBase(addressesProvider) { + ORACLE = IPriceOracleGetter(addressesProvider.getPriceOracle()); + UNISWAP_ROUTER = uniswapRouter; + WETH_ADDRESS = wethAddress; + } + + /** + * @dev Given an input asset amount, returns the maximum output amount of the other asset and the prices + * @param amountIn Amount of reserveIn + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @return uint256 Amount out of the reserveOut + * @return uint256 The price of out amount denominated in the reserveIn currency (18 decimals) + * @return uint256 In amount of reserveIn value denominated in USD (8 decimals) + * @return uint256 Out amount of reserveOut value denominated in USD (8 decimals) + */ + function getAmountsOut( + uint256 amountIn, + address reserveIn, + address reserveOut + ) + external + view + override + returns ( + uint256, + uint256, + uint256, + uint256, + address[] memory + ) + { + AmountCalc memory results = _getAmountsOutData(reserveIn, reserveOut, amountIn); + + return ( + results.calculatedAmount, + results.relativePrice, + results.amountInUsd, + results.amountOutUsd, + results.path + ); + } + + /** + * @dev Returns the minimum input asset amount required to buy the given output asset amount and the prices + * @param amountOut Amount of reserveOut + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @return uint256 Amount in of the reserveIn + * @return uint256 The price of in amount denominated in the reserveOut currency (18 decimals) + * @return uint256 In amount of reserveIn value denominated in USD (8 decimals) + * @return uint256 Out amount of reserveOut value denominated in USD (8 decimals) + */ + function getAmountsIn( + uint256 amountOut, + address reserveIn, + address reserveOut + ) + external + view + override + returns ( + uint256, + uint256, + uint256, + uint256, + address[] memory + ) + { + AmountCalc memory results = _getAmountsInData(reserveIn, reserveOut, amountOut); + + return ( + results.calculatedAmount, + results.relativePrice, + results.amountInUsd, + results.amountOutUsd, + results.path + ); + } + + /** + * @dev Swaps an exact `amountToSwap` of an asset to another + * @param assetToSwapFrom Origin asset + * @param assetToSwapTo Destination asset + * @param amountToSwap Exact amount of `assetToSwapFrom` to be swapped + * @param minAmountOut the min amount of `assetToSwapTo` to be received from the swap + * @return the amount received from the swap + */ + function _swapExactTokensForTokens( + address assetToSwapFrom, + address assetToSwapTo, + uint256 amountToSwap, + uint256 minAmountOut, + bool useEthPath + ) internal returns (uint256) { + uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom); + uint256 toAssetDecimals = _getDecimals(assetToSwapTo); + + uint256 fromAssetPrice = _getPrice(assetToSwapFrom); + uint256 toAssetPrice = _getPrice(assetToSwapTo); + + uint256 expectedMinAmountOut = + amountToSwap + .mul(fromAssetPrice.mul(10**toAssetDecimals)) + .div(toAssetPrice.mul(10**fromAssetDecimals)) + .percentMul(PercentageMath.PERCENTAGE_FACTOR.sub(MAX_SLIPPAGE_PERCENT)); + + require(expectedMinAmountOut < minAmountOut, 'minAmountOut exceed max slippage'); + + // Approves the transfer for the swap. Approves for 0 first to comply with tokens that implement the anti frontrunning approval fix. + IERC20(assetToSwapFrom).safeApprove(address(UNISWAP_ROUTER), 0); + IERC20(assetToSwapFrom).safeApprove(address(UNISWAP_ROUTER), amountToSwap); + + address[] memory path; + if (useEthPath) { + path = new address[](3); + path[0] = assetToSwapFrom; + path[1] = WETH_ADDRESS; + path[2] = assetToSwapTo; + } else { + path = new address[](2); + path[0] = assetToSwapFrom; + path[1] = assetToSwapTo; + } + uint256[] memory amounts = + UNISWAP_ROUTER.swapExactTokensForTokens( + amountToSwap, + minAmountOut, + path, + address(this), + block.timestamp + ); + + emit Swapped(assetToSwapFrom, assetToSwapTo, amounts[0], amounts[amounts.length - 1]); + + return amounts[amounts.length - 1]; + } + + /** + * @dev Receive an exact amount `amountToReceive` of `assetToSwapTo` tokens for as few `assetToSwapFrom` tokens as + * possible. + * @param assetToSwapFrom Origin asset + * @param assetToSwapTo Destination asset + * @param maxAmountToSwap Max amount of `assetToSwapFrom` allowed to be swapped + * @param amountToReceive Exact amount of `assetToSwapTo` to receive + * @return the amount swapped + */ + function _swapTokensForExactTokens( + address assetToSwapFrom, + address assetToSwapTo, + uint256 maxAmountToSwap, + uint256 amountToReceive, + bool useEthPath + ) internal returns (uint256) { + uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom); + uint256 toAssetDecimals = _getDecimals(assetToSwapTo); + + uint256 fromAssetPrice = _getPrice(assetToSwapFrom); + uint256 toAssetPrice = _getPrice(assetToSwapTo); + + uint256 expectedMaxAmountToSwap = + amountToReceive + .mul(toAssetPrice.mul(10**fromAssetDecimals)) + .div(fromAssetPrice.mul(10**toAssetDecimals)) + .percentMul(PercentageMath.PERCENTAGE_FACTOR.add(MAX_SLIPPAGE_PERCENT)); + + require(maxAmountToSwap < expectedMaxAmountToSwap, 'maxAmountToSwap exceed max slippage'); + + // Approves the transfer for the swap. Approves for 0 first to comply with tokens that implement the anti frontrunning approval fix. + IERC20(assetToSwapFrom).safeApprove(address(UNISWAP_ROUTER), 0); + IERC20(assetToSwapFrom).safeApprove(address(UNISWAP_ROUTER), maxAmountToSwap); + + address[] memory path; + if (useEthPath) { + path = new address[](3); + path[0] = assetToSwapFrom; + path[1] = WETH_ADDRESS; + path[2] = assetToSwapTo; + } else { + path = new address[](2); + path[0] = assetToSwapFrom; + path[1] = assetToSwapTo; + } + + uint256[] memory amounts = + UNISWAP_ROUTER.swapTokensForExactTokens( + amountToReceive, + maxAmountToSwap, + path, + address(this), + block.timestamp + ); + + emit Swapped(assetToSwapFrom, assetToSwapTo, amounts[0], amounts[amounts.length - 1]); + + return amounts[0]; + } + + /** + * @dev Get the price of the asset from the oracle denominated in eth + * @param asset address + * @return eth price for the asset + */ + function _getPrice(address asset) internal view returns (uint256) { + return ORACLE.getAssetPrice(asset); + } + + /** + * @dev Get the decimals of an asset + * @return number of decimals of the asset + */ + function _getDecimals(address asset) internal view returns (uint256) { + return IERC20Detailed(asset).decimals(); + } + + /** + * @dev Get the aToken associated to the asset + * @return address of the aToken + */ + function _getReserveData(address asset) internal view returns (DataTypes.ReserveData memory) { + return LENDING_POOL.getReserveData(asset); + } + + /** + * @dev Pull the ATokens from the user + * @param reserve address of the asset + * @param reserveAToken address of the aToken of the reserve + * @param user address + * @param amount of tokens to be transferred to the contract + * @param permitSignature struct containing the permit signature + */ + function _pullAToken( + address reserve, + address reserveAToken, + address user, + uint256 amount, + PermitSignature memory permitSignature + ) internal { + if (_usePermit(permitSignature)) { + IERC20WithPermit(reserveAToken).permit( + user, + address(this), + permitSignature.amount, + permitSignature.deadline, + permitSignature.v, + permitSignature.r, + permitSignature.s + ); + } + + // transfer from user to adapter + IERC20(reserveAToken).safeTransferFrom(user, address(this), amount); + + // withdraw reserve + LENDING_POOL.withdraw(reserve, amount, address(this)); + } + + /** + * @dev Tells if the permit method should be called by inspecting if there is a valid signature. + * If signature params are set to 0, then permit won't be called. + * @param signature struct containing the permit signature + * @return whether or not permit should be called + */ + function _usePermit(PermitSignature memory signature) internal pure returns (bool) { + return + !(uint256(signature.deadline) == uint256(signature.v) && uint256(signature.deadline) == 0); + } + + /** + * @dev Calculates the value denominated in USD + * @param reserve Address of the reserve + * @param amount Amount of the reserve + * @param decimals Decimals of the reserve + * @return whether or not permit should be called + */ + function _calcUsdValue( + address reserve, + uint256 amount, + uint256 decimals + ) internal view returns (uint256) { + uint256 ethUsdPrice = _getPrice(USD_ADDRESS); + uint256 reservePrice = _getPrice(reserve); + + return amount.mul(reservePrice).div(10**decimals).mul(ethUsdPrice).div(10**18); + } + + /** + * @dev Given an input asset amount, returns the maximum output amount of the other asset + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @param amountIn Amount of reserveIn + * @return Struct containing the following information: + * uint256 Amount out of the reserveOut + * uint256 The price of out amount denominated in the reserveIn currency (18 decimals) + * uint256 In amount of reserveIn value denominated in USD (8 decimals) + * uint256 Out amount of reserveOut value denominated in USD (8 decimals) + */ + function _getAmountsOutData( + address reserveIn, + address reserveOut, + uint256 amountIn + ) internal view returns (AmountCalc memory) { + // Subtract flash loan fee + uint256 finalAmountIn = amountIn.sub(amountIn.mul(FLASHLOAN_PREMIUM_TOTAL).div(10000)); + + address[] memory simplePath = new address[](2); + simplePath[0] = reserveIn; + simplePath[1] = reserveOut; + + uint256[] memory amountsWithoutWeth; + uint256[] memory amountsWithWeth; + + address[] memory pathWithWeth = new address[](3); + if (reserveIn != WETH_ADDRESS && reserveOut != WETH_ADDRESS) { + pathWithWeth[0] = reserveIn; + pathWithWeth[1] = WETH_ADDRESS; + pathWithWeth[2] = reserveOut; + + try UNISWAP_ROUTER.getAmountsOut(finalAmountIn, pathWithWeth) returns ( + uint256[] memory resultsWithWeth + ) { + amountsWithWeth = resultsWithWeth; + } catch { + amountsWithWeth = new uint256[](3); + } + } else { + amountsWithWeth = new uint256[](3); + } + + uint256 bestAmountOut; + try UNISWAP_ROUTER.getAmountsOut(finalAmountIn, simplePath) returns ( + uint256[] memory resultAmounts + ) { + amountsWithoutWeth = resultAmounts; + + bestAmountOut = (amountsWithWeth[2] > amountsWithoutWeth[1]) + ? amountsWithWeth[2] + : amountsWithoutWeth[1]; + } catch { + amountsWithoutWeth = new uint256[](2); + bestAmountOut = amountsWithWeth[2]; + } + + uint256 reserveInDecimals = _getDecimals(reserveIn); + uint256 reserveOutDecimals = _getDecimals(reserveOut); + + uint256 outPerInPrice = + finalAmountIn.mul(10**18).mul(10**reserveOutDecimals).div( + bestAmountOut.mul(10**reserveInDecimals) + ); + + return + AmountCalc( + bestAmountOut, + outPerInPrice, + _calcUsdValue(reserveIn, amountIn, reserveInDecimals), + _calcUsdValue(reserveOut, bestAmountOut, reserveOutDecimals), + (bestAmountOut == 0) ? new address[](2) : (bestAmountOut == amountsWithoutWeth[1]) + ? simplePath + : pathWithWeth + ); + } + + /** + * @dev Returns the minimum input asset amount required to buy the given output asset amount + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @param amountOut Amount of reserveOut + * @return Struct containing the following information: + * uint256 Amount in of the reserveIn + * uint256 The price of in amount denominated in the reserveOut currency (18 decimals) + * uint256 In amount of reserveIn value denominated in USD (8 decimals) + * uint256 Out amount of reserveOut value denominated in USD (8 decimals) + */ + function _getAmountsInData( + address reserveIn, + address reserveOut, + uint256 amountOut + ) internal view returns (AmountCalc memory) { + (uint256[] memory amounts, address[] memory path) = + _getAmountsInAndPath(reserveIn, reserveOut, amountOut); + + // Add flash loan fee + uint256 finalAmountIn = amounts[0].add(amounts[0].mul(FLASHLOAN_PREMIUM_TOTAL).div(10000)); + + uint256 reserveInDecimals = _getDecimals(reserveIn); + uint256 reserveOutDecimals = _getDecimals(reserveOut); + + uint256 inPerOutPrice = + amountOut.mul(10**18).mul(10**reserveInDecimals).div( + finalAmountIn.mul(10**reserveOutDecimals) + ); + + return + AmountCalc( + finalAmountIn, + inPerOutPrice, + _calcUsdValue(reserveIn, finalAmountIn, reserveInDecimals), + _calcUsdValue(reserveOut, amountOut, reserveOutDecimals), + path + ); + } + + /** + * @dev Calculates the input asset amount required to buy the given output asset amount + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @param amountOut Amount of reserveOut + * @return uint256[] amounts Array containing the amountIn and amountOut for a swap + */ + function _getAmountsInAndPath( + address reserveIn, + address reserveOut, + uint256 amountOut + ) internal view returns (uint256[] memory, address[] memory) { + address[] memory simplePath = new address[](2); + simplePath[0] = reserveIn; + simplePath[1] = reserveOut; + + uint256[] memory amountsWithoutWeth; + uint256[] memory amountsWithWeth; + address[] memory pathWithWeth = new address[](3); + + if (reserveIn != WETH_ADDRESS && reserveOut != WETH_ADDRESS) { + pathWithWeth[0] = reserveIn; + pathWithWeth[1] = WETH_ADDRESS; + pathWithWeth[2] = reserveOut; + + try UNISWAP_ROUTER.getAmountsIn(amountOut, pathWithWeth) returns ( + uint256[] memory resultsWithWeth + ) { + amountsWithWeth = resultsWithWeth; + } catch { + amountsWithWeth = new uint256[](3); + } + } else { + amountsWithWeth = new uint256[](3); + } + + try UNISWAP_ROUTER.getAmountsIn(amountOut, simplePath) returns ( + uint256[] memory resultAmounts + ) { + amountsWithoutWeth = resultAmounts; + + return + (amountsWithWeth[0] < amountsWithoutWeth[0] && amountsWithWeth[0] != 0) + ? (amountsWithWeth, pathWithWeth) + : (amountsWithoutWeth, simplePath); + } catch { + return (amountsWithWeth, pathWithWeth); + } + } + + /** + * @dev Calculates the input asset amount required to buy the given output asset amount + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @param amountOut Amount of reserveOut + * @return uint256[] amounts Array containing the amountIn and amountOut for a swap + */ + function _getAmountsIn( + address reserveIn, + address reserveOut, + uint256 amountOut, + bool useEthPath + ) internal view returns (uint256[] memory) { + address[] memory path; + + if (useEthPath) { + path = new address[](3); + path[0] = reserveIn; + path[1] = WETH_ADDRESS; + path[2] = reserveOut; + } else { + path = new address[](2); + path[0] = reserveIn; + path[1] = reserveOut; + } + + return UNISWAP_ROUTER.getAmountsIn(amountOut, path); + } + + /** + * @dev Emergency rescue for token stucked on this contract, as failsafe mechanism + * - Funds should never remain in this contract more time than during transactions + * - Only callable by the owner + **/ + function rescueTokens(IERC20 token) external onlyOwner { + token.transfer(owner(), token.balanceOf(address(this))); + } +} diff --git a/contracts/adapters/UniswapLiquiditySwapAdapter.sol b/contracts/adapters/UniswapLiquiditySwapAdapter.sol new file mode 100644 index 00000000..44745ad5 --- /dev/null +++ b/contracts/adapters/UniswapLiquiditySwapAdapter.sol @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {BaseUniswapAdapter} from './BaseUniswapAdapter.sol'; +import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; +import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol'; +import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; + +/** + * @title UniswapLiquiditySwapAdapter + * @notice Uniswap V2 Adapter to swap liquidity. + * @author Aave + **/ +contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter { + struct PermitParams { + uint256[] amount; + uint256[] deadline; + uint8[] v; + bytes32[] r; + bytes32[] s; + } + + struct SwapParams { + address[] assetToSwapToList; + uint256[] minAmountsToReceive; + bool[] swapAllBalance; + PermitParams permitParams; + bool[] useEthPath; + } + + constructor( + ILendingPoolAddressesProvider addressesProvider, + IUniswapV2Router02 uniswapRouter, + address wethAddress + ) public BaseUniswapAdapter(addressesProvider, uniswapRouter, wethAddress) {} + + /** + * @dev Swaps the received reserve amount from the flash loan into the asset specified in the params. + * The received funds from the swap are then deposited into the protocol on behalf of the user. + * The user should give this contract allowance to pull the ATokens in order to withdraw the underlying asset and + * repay the flash loan. + * @param assets Address of asset to be swapped + * @param amounts Amount of the asset to be swapped + * @param premiums Fee of the flash loan + * @param initiator Address of the user + * @param params Additional variadic field to include extra params. Expected parameters: + * address[] assetToSwapToList List of the addresses of the reserve to be swapped to and deposited + * uint256[] minAmountsToReceive List of min amounts to be received from the swap + * bool[] swapAllBalance Flag indicating if all the user balance should be swapped + * uint256[] permitAmount List of amounts for the permit signature + * uint256[] deadline List of deadlines for the permit signature + * uint8[] v List of v param for the permit signature + * bytes32[] r List of r param for the permit signature + * bytes32[] s List of s param for the permit signature + */ + function executeOperation( + address[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata premiums, + address initiator, + bytes calldata params + ) external override returns (bool) { + require(msg.sender == address(LENDING_POOL), 'CALLER_MUST_BE_LENDING_POOL'); + + SwapParams memory decodedParams = _decodeParams(params); + + require( + assets.length == decodedParams.assetToSwapToList.length && + assets.length == decodedParams.minAmountsToReceive.length && + assets.length == decodedParams.swapAllBalance.length && + assets.length == decodedParams.permitParams.amount.length && + assets.length == decodedParams.permitParams.deadline.length && + assets.length == decodedParams.permitParams.v.length && + assets.length == decodedParams.permitParams.r.length && + assets.length == decodedParams.permitParams.s.length && + assets.length == decodedParams.useEthPath.length, + 'INCONSISTENT_PARAMS' + ); + + for (uint256 i = 0; i < assets.length; i++) { + _swapLiquidity( + assets[i], + decodedParams.assetToSwapToList[i], + amounts[i], + premiums[i], + initiator, + decodedParams.minAmountsToReceive[i], + decodedParams.swapAllBalance[i], + PermitSignature( + decodedParams.permitParams.amount[i], + decodedParams.permitParams.deadline[i], + decodedParams.permitParams.v[i], + decodedParams.permitParams.r[i], + decodedParams.permitParams.s[i] + ), + decodedParams.useEthPath[i] + ); + } + + return true; + } + + struct SwapAndDepositLocalVars { + uint256 i; + uint256 aTokenInitiatorBalance; + uint256 amountToSwap; + uint256 receivedAmount; + address aToken; + } + + /** + * @dev Swaps an amount of an asset to another and deposits the new asset amount on behalf of the user without using + * a flash loan. This method can be used when the temporary transfer of the collateral asset to this contract + * does not affect the user position. + * The user should give this contract allowance to pull the ATokens in order to withdraw the underlying asset and + * perform the swap. + * @param assetToSwapFromList List of addresses of the underlying asset to be swap from + * @param assetToSwapToList List of addresses of the underlying asset to be swap to and deposited + * @param amountToSwapList List of amounts to be swapped. If the amount exceeds the balance, the total balance is used for the swap + * @param minAmountsToReceive List of min amounts to be received from the swap + * @param permitParams List of struct containing the permit signatures + * uint256 permitAmount Amount for the permit signature + * uint256 deadline Deadline for the permit signature + * uint8 v param for the permit signature + * bytes32 r param for the permit signature + * bytes32 s param for the permit signature + * @param useEthPath true if the swap needs to occur using ETH in the routing, false otherwise + */ + function swapAndDeposit( + address[] calldata assetToSwapFromList, + address[] calldata assetToSwapToList, + uint256[] calldata amountToSwapList, + uint256[] calldata minAmountsToReceive, + PermitSignature[] calldata permitParams, + bool[] calldata useEthPath + ) external { + require( + assetToSwapFromList.length == assetToSwapToList.length && + assetToSwapFromList.length == amountToSwapList.length && + assetToSwapFromList.length == minAmountsToReceive.length && + assetToSwapFromList.length == permitParams.length, + 'INCONSISTENT_PARAMS' + ); + + SwapAndDepositLocalVars memory vars; + + for (vars.i = 0; vars.i < assetToSwapFromList.length; vars.i++) { + vars.aToken = _getReserveData(assetToSwapFromList[vars.i]).aTokenAddress; + + vars.aTokenInitiatorBalance = IERC20(vars.aToken).balanceOf(msg.sender); + vars.amountToSwap = amountToSwapList[vars.i] > vars.aTokenInitiatorBalance + ? vars.aTokenInitiatorBalance + : amountToSwapList[vars.i]; + + _pullAToken( + assetToSwapFromList[vars.i], + vars.aToken, + msg.sender, + vars.amountToSwap, + permitParams[vars.i] + ); + + vars.receivedAmount = _swapExactTokensForTokens( + assetToSwapFromList[vars.i], + assetToSwapToList[vars.i], + vars.amountToSwap, + minAmountsToReceive[vars.i], + useEthPath[vars.i] + ); + + // Deposit new reserve + IERC20(assetToSwapToList[vars.i]).safeApprove(address(LENDING_POOL), 0); + IERC20(assetToSwapToList[vars.i]).safeApprove(address(LENDING_POOL), vars.receivedAmount); + LENDING_POOL.deposit(assetToSwapToList[vars.i], vars.receivedAmount, msg.sender, 0); + } + } + + /** + * @dev Swaps an `amountToSwap` of an asset to another and deposits the funds on behalf of the initiator. + * @param assetFrom Address of the underlying asset to be swap from + * @param assetTo Address of the underlying asset to be swap to and deposited + * @param amount Amount from flash loan + * @param premium Premium of the flash loan + * @param minAmountToReceive Min amount to be received from the swap + * @param swapAllBalance Flag indicating if all the user balance should be swapped + * @param permitSignature List of struct containing the permit signature + * @param useEthPath true if the swap needs to occur using ETH in the routing, false otherwise + */ + + struct SwapLiquidityLocalVars { + address aToken; + uint256 aTokenInitiatorBalance; + uint256 amountToSwap; + uint256 receivedAmount; + uint256 flashLoanDebt; + uint256 amountToPull; + } + + function _swapLiquidity( + address assetFrom, + address assetTo, + uint256 amount, + uint256 premium, + address initiator, + uint256 minAmountToReceive, + bool swapAllBalance, + PermitSignature memory permitSignature, + bool useEthPath + ) internal { + + SwapLiquidityLocalVars memory vars; + + vars.aToken = _getReserveData(assetFrom).aTokenAddress; + + vars.aTokenInitiatorBalance = IERC20(vars.aToken).balanceOf(initiator); + vars.amountToSwap = + swapAllBalance && vars.aTokenInitiatorBalance.sub(premium) <= amount + ? vars.aTokenInitiatorBalance.sub(premium) + : amount; + + vars.receivedAmount = + _swapExactTokensForTokens(assetFrom, assetTo, vars.amountToSwap, minAmountToReceive, useEthPath); + + // Deposit new reserve + IERC20(assetTo).safeApprove(address(LENDING_POOL), 0); + IERC20(assetTo).safeApprove(address(LENDING_POOL), vars.receivedAmount); + LENDING_POOL.deposit(assetTo, vars.receivedAmount, initiator, 0); + + vars.flashLoanDebt = amount.add(premium); + vars.amountToPull = vars.amountToSwap.add(premium); + + _pullAToken(assetFrom, vars.aToken, initiator, vars.amountToPull, permitSignature); + + // Repay flash loan + IERC20(assetFrom).safeApprove(address(LENDING_POOL), 0); + IERC20(assetFrom).safeApprove(address(LENDING_POOL), vars.flashLoanDebt); + } + + /** + * @dev Decodes the information encoded in the flash loan params + * @param params Additional variadic field to include extra params. Expected parameters: + * address[] assetToSwapToList List of the addresses of the reserve to be swapped to and deposited + * uint256[] minAmountsToReceive List of min amounts to be received from the swap + * bool[] swapAllBalance Flag indicating if all the user balance should be swapped + * uint256[] permitAmount List of amounts for the permit signature + * uint256[] deadline List of deadlines for the permit signature + * uint8[] v List of v param for the permit signature + * bytes32[] r List of r param for the permit signature + * bytes32[] s List of s param for the permit signature + * bool[] useEthPath true if the swap needs to occur using ETH in the routing, false otherwise + * @return SwapParams struct containing decoded params + */ + function _decodeParams(bytes memory params) internal pure returns (SwapParams memory) { + ( + address[] memory assetToSwapToList, + uint256[] memory minAmountsToReceive, + bool[] memory swapAllBalance, + uint256[] memory permitAmount, + uint256[] memory deadline, + uint8[] memory v, + bytes32[] memory r, + bytes32[] memory s, + bool[] memory useEthPath + ) = + abi.decode( + params, + (address[], uint256[], bool[], uint256[], uint256[], uint8[], bytes32[], bytes32[], bool[]) + ); + + return + SwapParams( + assetToSwapToList, + minAmountsToReceive, + swapAllBalance, + PermitParams(permitAmount, deadline, v, r, s), + useEthPath + ); + } +} \ No newline at end of file diff --git a/contracts/adapters/UniswapRepayAdapter.sol b/contracts/adapters/UniswapRepayAdapter.sol new file mode 100644 index 00000000..c4e7817e --- /dev/null +++ b/contracts/adapters/UniswapRepayAdapter.sol @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {BaseUniswapAdapter} from './BaseUniswapAdapter.sol'; +import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; +import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol'; +import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; +import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; + +/** + * @title UniswapRepayAdapter + * @notice Uniswap V2 Adapter to perform a repay of a debt with collateral. + * @author Aave + **/ +contract UniswapRepayAdapter is BaseUniswapAdapter { + struct RepayParams { + address collateralAsset; + uint256 collateralAmount; + uint256 rateMode; + PermitSignature permitSignature; + bool useEthPath; + } + + constructor( + ILendingPoolAddressesProvider addressesProvider, + IUniswapV2Router02 uniswapRouter, + address wethAddress + ) public BaseUniswapAdapter(addressesProvider, uniswapRouter, wethAddress) {} + + /** + * @dev Uses the received funds from the flash loan to repay a debt on the protocol on behalf of the user. Then pulls + * the collateral from the user and swaps it to the debt asset to repay the flash loan. + * The user should give this contract allowance to pull the ATokens in order to withdraw the underlying asset, swap it + * and repay the flash loan. + * Supports only one asset on the flash loan. + * @param assets Address of debt asset + * @param amounts Amount of the debt to be repaid + * @param premiums Fee of the flash loan + * @param initiator Address of the user + * @param params Additional variadic field to include extra params. Expected parameters: + * address collateralAsset Address of the reserve to be swapped + * uint256 collateralAmount Amount of reserve to be swapped + * uint256 rateMode Rate modes of the debt to be repaid + * uint256 permitAmount Amount for the permit signature + * uint256 deadline Deadline for the permit signature + * uint8 v V param for the permit signature + * bytes32 r R param for the permit signature + * bytes32 s S param for the permit signature + */ + function executeOperation( + address[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata premiums, + address initiator, + bytes calldata params + ) external override returns (bool) { + require(msg.sender == address(LENDING_POOL), 'CALLER_MUST_BE_LENDING_POOL'); + + RepayParams memory decodedParams = _decodeParams(params); + + _swapAndRepay( + decodedParams.collateralAsset, + assets[0], + amounts[0], + decodedParams.collateralAmount, + decodedParams.rateMode, + initiator, + premiums[0], + decodedParams.permitSignature, + decodedParams.useEthPath + ); + + return true; + } + + /** + * @dev Swaps the user collateral for the debt asset and then repay the debt on the protocol on behalf of the user + * without using flash loans. This method can be used when the temporary transfer of the collateral asset to this + * contract does not affect the user position. + * The user should give this contract allowance to pull the ATokens in order to withdraw the underlying asset + * @param collateralAsset Address of asset to be swapped + * @param debtAsset Address of debt asset + * @param collateralAmount Amount of the collateral to be swapped + * @param debtRepayAmount Amount of the debt to be repaid + * @param debtRateMode Rate mode of the debt to be repaid + * @param permitSignature struct containing the permit signature + * @param useEthPath struct containing the permit signature + + */ + function swapAndRepay( + address collateralAsset, + address debtAsset, + uint256 collateralAmount, + uint256 debtRepayAmount, + uint256 debtRateMode, + PermitSignature calldata permitSignature, + bool useEthPath + ) external { + DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset); + DataTypes.ReserveData memory debtReserveData = _getReserveData(debtAsset); + + address debtToken = + DataTypes.InterestRateMode(debtRateMode) == DataTypes.InterestRateMode.STABLE + ? debtReserveData.stableDebtTokenAddress + : debtReserveData.variableDebtTokenAddress; + + uint256 currentDebt = IERC20(debtToken).balanceOf(msg.sender); + uint256 amountToRepay = debtRepayAmount <= currentDebt ? debtRepayAmount : currentDebt; + + if (collateralAsset != debtAsset) { + uint256 maxCollateralToSwap = collateralAmount; + if (amountToRepay < debtRepayAmount) { + maxCollateralToSwap = maxCollateralToSwap.mul(amountToRepay).div(debtRepayAmount); + } + + // Get exact collateral needed for the swap to avoid leftovers + uint256[] memory amounts = + _getAmountsIn(collateralAsset, debtAsset, amountToRepay, useEthPath); + require(amounts[0] <= maxCollateralToSwap, 'slippage too high'); + + // Pull aTokens from user + _pullAToken( + collateralAsset, + collateralReserveData.aTokenAddress, + msg.sender, + amounts[0], + permitSignature + ); + + // Swap collateral for debt asset + _swapTokensForExactTokens(collateralAsset, debtAsset, amounts[0], amountToRepay, useEthPath); + } else { + // Pull aTokens from user + _pullAToken( + collateralAsset, + collateralReserveData.aTokenAddress, + msg.sender, + amountToRepay, + permitSignature + ); + } + + // Repay debt. Approves 0 first to comply with tokens that implement the anti frontrunning approval fix + IERC20(debtAsset).safeApprove(address(LENDING_POOL), 0); + IERC20(debtAsset).safeApprove(address(LENDING_POOL), amountToRepay); + LENDING_POOL.repay(debtAsset, amountToRepay, debtRateMode, msg.sender); + } + + /** + * @dev Perform the repay of the debt, pulls the initiator collateral and swaps to repay the flash loan + * + * @param collateralAsset Address of token to be swapped + * @param debtAsset Address of debt token to be received from the swap + * @param amount Amount of the debt to be repaid + * @param collateralAmount Amount of the reserve to be swapped + * @param rateMode Rate mode of the debt to be repaid + * @param initiator Address of the user + * @param premium Fee of the flash loan + * @param permitSignature struct containing the permit signature + */ + function _swapAndRepay( + address collateralAsset, + address debtAsset, + uint256 amount, + uint256 collateralAmount, + uint256 rateMode, + address initiator, + uint256 premium, + PermitSignature memory permitSignature, + bool useEthPath + ) internal { + DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset); + + // Repay debt. Approves for 0 first to comply with tokens that implement the anti frontrunning approval fix. + IERC20(debtAsset).safeApprove(address(LENDING_POOL), 0); + IERC20(debtAsset).safeApprove(address(LENDING_POOL), amount); + uint256 repaidAmount = IERC20(debtAsset).balanceOf(address(this)); + LENDING_POOL.repay(debtAsset, amount, rateMode, initiator); + repaidAmount = repaidAmount.sub(IERC20(debtAsset).balanceOf(address(this))); + + if (collateralAsset != debtAsset) { + uint256 maxCollateralToSwap = collateralAmount; + if (repaidAmount < amount) { + maxCollateralToSwap = maxCollateralToSwap.mul(repaidAmount).div(amount); + } + + uint256 neededForFlashLoanDebt = repaidAmount.add(premium); + uint256[] memory amounts = + _getAmountsIn(collateralAsset, debtAsset, neededForFlashLoanDebt, useEthPath); + require(amounts[0] <= maxCollateralToSwap, 'slippage too high'); + + // Pull aTokens from user + _pullAToken( + collateralAsset, + collateralReserveData.aTokenAddress, + initiator, + amounts[0], + permitSignature + ); + + // Swap collateral asset to the debt asset + _swapTokensForExactTokens(collateralAsset, debtAsset, amounts[0], neededForFlashLoanDebt, useEthPath); + } else { + // Pull aTokens from user + _pullAToken( + collateralAsset, + collateralReserveData.aTokenAddress, + initiator, + repaidAmount.add(premium), + permitSignature + ); + } + + // Repay flashloan. Approves for 0 first to comply with tokens that implement the anti frontrunning approval fix. + IERC20(debtAsset).safeApprove(address(LENDING_POOL), 0); + IERC20(debtAsset).safeApprove(address(LENDING_POOL), amount.add(premium)); + } + + /** + * @dev Decodes debt information encoded in the flash loan params + * @param params Additional variadic field to include extra params. Expected parameters: + * address collateralAsset Address of the reserve to be swapped + * uint256 collateralAmount Amount of reserve to be swapped + * uint256 rateMode Rate modes of the debt to be repaid + * uint256 permitAmount Amount for the permit signature + * uint256 deadline Deadline for the permit signature + * uint8 v V param for the permit signature + * bytes32 r R param for the permit signature + * bytes32 s S param for the permit signature + * @return RepayParams struct containing decoded params + */ + function _decodeParams(bytes memory params) internal pure returns (RepayParams memory) { + ( + address collateralAsset, + uint256 collateralAmount, + uint256 rateMode, + uint256 permitAmount, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s, + bool useEthPath + ) = + abi.decode( + params, + (address, uint256, uint256, uint256, uint256, uint8, bytes32, bytes32, bool) + ); + + return + RepayParams( + collateralAsset, + collateralAmount, + rateMode, + PermitSignature(permitAmount, deadline, v, r, s), + useEthPath + ); + } +} \ No newline at end of file diff --git a/contracts/adapters/interfaces/IBaseUniswapAdapter.sol b/contracts/adapters/interfaces/IBaseUniswapAdapter.sol new file mode 100644 index 00000000..82997b74 --- /dev/null +++ b/contracts/adapters/interfaces/IBaseUniswapAdapter.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol'; +import {IUniswapV2Router02} from '../../interfaces/IUniswapV2Router02.sol'; + +interface IBaseUniswapAdapter { + event Swapped(address fromAsset, address toAsset, uint256 fromAmount, uint256 receivedAmount); + + struct PermitSignature { + uint256 amount; + uint256 deadline; + uint8 v; + bytes32 r; + bytes32 s; + } + + struct AmountCalc { + uint256 calculatedAmount; + uint256 relativePrice; + uint256 amountInUsd; + uint256 amountOutUsd; + address[] path; + } + + function WETH_ADDRESS() external returns (address); + + function MAX_SLIPPAGE_PERCENT() external returns (uint256); + + function FLASHLOAN_PREMIUM_TOTAL() external returns (uint256); + + function USD_ADDRESS() external returns (address); + + function ORACLE() external returns (IPriceOracleGetter); + + function UNISWAP_ROUTER() external returns (IUniswapV2Router02); + + /** + * @dev Given an input asset amount, returns the maximum output amount of the other asset and the prices + * @param amountIn Amount of reserveIn + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @return uint256 Amount out of the reserveOut + * @return uint256 The price of out amount denominated in the reserveIn currency (18 decimals) + * @return uint256 In amount of reserveIn value denominated in USD (8 decimals) + * @return uint256 Out amount of reserveOut value denominated in USD (8 decimals) + * @return address[] The exchange path + */ + function getAmountsOut( + uint256 amountIn, + address reserveIn, + address reserveOut + ) + external + view + returns ( + uint256, + uint256, + uint256, + uint256, + address[] memory + ); + + /** + * @dev Returns the minimum input asset amount required to buy the given output asset amount and the prices + * @param amountOut Amount of reserveOut + * @param reserveIn Address of the asset to be swap from + * @param reserveOut Address of the asset to be swap to + * @return uint256 Amount in of the reserveIn + * @return uint256 The price of in amount denominated in the reserveOut currency (18 decimals) + * @return uint256 In amount of reserveIn value denominated in USD (8 decimals) + * @return uint256 Out amount of reserveOut value denominated in USD (8 decimals) + * @return address[] The exchange path + */ + function getAmountsIn( + uint256 amountOut, + address reserveIn, + address reserveOut + ) + external + view + returns ( + uint256, + uint256, + uint256, + uint256, + address[] memory + ); +} diff --git a/contracts/deployments/ATokensAndRatesHelper.sol b/contracts/deployments/ATokensAndRatesHelper.sol index a29dc6f2..400f7ca6 100644 --- a/contracts/deployments/ATokensAndRatesHelper.sol +++ b/contracts/deployments/ATokensAndRatesHelper.sol @@ -20,6 +20,20 @@ contract ATokensAndRatesHelper is Ownable { address private poolConfigurator; event deployedContracts(address aToken, address strategy); + struct InitDeploymentInput { + address asset; + uint256[6] rates; + } + + struct ConfigureReserveInput { + address asset; + uint256 baseLTV; + uint256 liquidationThreshold; + uint256 liquidationBonus; + uint256 reserveFactor; + bool stableBorrowingEnabled; + } + constructor( address payable _pool, address _addressesProvider, @@ -30,93 +44,40 @@ contract ATokensAndRatesHelper is Ownable { poolConfigurator = _poolConfigurator; } - function initDeployment( - address[] calldata assets, - string[] calldata symbols, - uint256[6][] calldata rates, - address treasuryAddress, - address incentivesController - ) external onlyOwner { - require(assets.length == symbols.length, 't Arrays not same length'); - require(rates.length == symbols.length, 'r Arrays not same length'); - for (uint256 i = 0; i < assets.length; i++) { + function initDeployment(InitDeploymentInput[] calldata inputParams) external onlyOwner { + for (uint256 i = 0; i < inputParams.length; i++) { emit deployedContracts( - address( - new AToken( - LendingPool(pool), - assets[i], - treasuryAddress, - StringLib.concat('Aave interest bearing ', symbols[i]), - StringLib.concat('a', symbols[i]), - incentivesController - ) - ), + address(new AToken()), address( new DefaultReserveInterestRateStrategy( LendingPoolAddressesProvider(addressesProvider), - rates[i][0], - rates[i][1], - rates[i][2], - rates[i][3], - rates[i][4], - rates[i][5] + inputParams[i].rates[0], + inputParams[i].rates[1], + inputParams[i].rates[2], + inputParams[i].rates[3], + inputParams[i].rates[4], + inputParams[i].rates[5] ) ) ); } } - function initReserve( - address[] calldata stables, - address[] calldata variables, - address[] calldata aTokens, - address[] calldata strategies, - uint8[] calldata reserveDecimals - ) external onlyOwner { - require(variables.length == stables.length); - require(aTokens.length == stables.length); - require(strategies.length == stables.length); - require(reserveDecimals.length == stables.length); - - for (uint256 i = 0; i < stables.length; i++) { - LendingPoolConfigurator(poolConfigurator).initReserve( - aTokens[i], - stables[i], - variables[i], - reserveDecimals[i], - strategies[i] - ); - } - } - - function configureReserves( - address[] calldata assets, - uint256[] calldata baseLTVs, - uint256[] calldata liquidationThresholds, - uint256[] calldata liquidationBonuses, - uint256[] calldata reserveFactors, - bool[] calldata stableBorrowingEnabled - ) external onlyOwner { - require(baseLTVs.length == assets.length); - require(liquidationThresholds.length == assets.length); - require(liquidationBonuses.length == assets.length); - require(stableBorrowingEnabled.length == assets.length); - require(reserveFactors.length == assets.length); - + function configureReserves(ConfigureReserveInput[] calldata inputParams) external onlyOwner { LendingPoolConfigurator configurator = LendingPoolConfigurator(poolConfigurator); - for (uint256 i = 0; i < assets.length; i++) { + for (uint256 i = 0; i < inputParams.length; i++) { configurator.configureReserveAsCollateral( - assets[i], - baseLTVs[i], - liquidationThresholds[i], - liquidationBonuses[i] + inputParams[i].asset, + inputParams[i].baseLTV, + inputParams[i].liquidationThreshold, + inputParams[i].liquidationBonus ); configurator.enableBorrowingOnReserve( - assets[i], - stableBorrowingEnabled[i] + inputParams[i].asset, + inputParams[i].stableBorrowingEnabled ); - configurator.setReserveFactor(assets[i], reserveFactors[i]); + configurator.setReserveFactor(inputParams[i].asset, inputParams[i].reserveFactor); } } } diff --git a/contracts/deployments/StableAndVariableTokensHelper.sol b/contracts/deployments/StableAndVariableTokensHelper.sol index 8f76bbe1..e31651f3 100644 --- a/contracts/deployments/StableAndVariableTokensHelper.sol +++ b/contracts/deployments/StableAndVariableTokensHelper.sol @@ -18,34 +18,11 @@ contract StableAndVariableTokensHelper is Ownable { addressesProvider = _addressesProvider; } - function initDeployment( - address[] calldata tokens, - string[] calldata symbols, - address incentivesController - ) external onlyOwner { + function initDeployment(address[] calldata tokens, string[] calldata symbols) 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++) { - emit deployedContracts( - address( - new StableDebtToken( - pool, - tokens[i], - StringLib.concat('Aave stable debt bearing ', symbols[i]), - StringLib.concat('stableDebt', symbols[i]), - incentivesController - ) - ), - address( - new VariableDebtToken( - pool, - tokens[i], - StringLib.concat('Aave variable debt bearing ', symbols[i]), - StringLib.concat('variableDebt', symbols[i]), - incentivesController - ) - ) - ); + emit deployedContracts(address(new StableDebtToken()), address(new VariableDebtToken())); } } diff --git a/contracts/interfaces/IAToken.sol b/contracts/interfaces/IAToken.sol index 5fa1a4f0..ca338270 100644 --- a/contracts/interfaces/IAToken.sol +++ b/contracts/interfaces/IAToken.sol @@ -3,8 +3,10 @@ pragma solidity 0.6.12; import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; import {IScaledBalanceToken} from './IScaledBalanceToken.sol'; +import {IInitializableAToken} from './IInitializableAToken.sol'; +import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; -interface IAToken is IERC20, IScaledBalanceToken { +interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken { /** * @dev Emitted after the mint action * @param from The address performing the mint @@ -85,4 +87,9 @@ interface IAToken is IERC20, IScaledBalanceToken { * @return The amount transferred **/ function transferUnderlyingTo(address user, uint256 amount) external returns (uint256); + + /** + * @dev Returns the address of the incentives controller contract + **/ + function getIncentivesController() external view returns (IAaveIncentivesController); } diff --git a/contracts/interfaces/IERC20WithPermit.sol b/contracts/interfaces/IERC20WithPermit.sol new file mode 100644 index 00000000..46466b90 --- /dev/null +++ b/contracts/interfaces/IERC20WithPermit.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; + +import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; + +interface IERC20WithPermit is IERC20 { + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; +} diff --git a/contracts/interfaces/IInitializableAToken.sol b/contracts/interfaces/IInitializableAToken.sol new file mode 100644 index 00000000..9cffe6ce --- /dev/null +++ b/contracts/interfaces/IInitializableAToken.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; + +import {ILendingPool} from './ILendingPool.sol'; +import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; + +/** + * @title IInitializableAToken + * @notice Interface for the initialize function on AToken + * @author Aave + **/ +interface IInitializableAToken { + /** + * @dev Initializes the aToken + * @param pool The address of the lending pool where this aToken will be used + * @param treasury The address of the Aave treasury, receiving the fees on this aToken + * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) + * @param incentivesController The smart contract managing potential incentives distribution + * @param aTokenDecimals The decimals of the aToken, same as the underlying asset's + * @param aTokenName The name of the aToken + * @param aTokenSymbol The symbol of the aToken + */ + function initialize( + ILendingPool pool, + address treasury, + address underlyingAsset, + IAaveIncentivesController incentivesController, + uint8 aTokenDecimals, + string calldata aTokenName, + string calldata aTokenSymbol + ) external; +} diff --git a/contracts/interfaces/IInitializableDebtToken.sol b/contracts/interfaces/IInitializableDebtToken.sol new file mode 100644 index 00000000..0a85c968 --- /dev/null +++ b/contracts/interfaces/IInitializableDebtToken.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; + +import {ILendingPool} from './ILendingPool.sol'; +import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; + +/** + * @title IInitializableDebtToken + * @notice Interface for the initialize function common between debt tokens + * @author Aave + **/ +interface IInitializableDebtToken { + /** + * @dev Initializes the debt token. + * @param pool The address of the lending pool where this aToken will be used + * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) + * @param incentivesController The smart contract managing potential incentives distribution + * @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's + * @param debtTokenName The name of the token + * @param debtTokenSymbol The symbol of the token + */ + function initialize( + ILendingPool pool, + address underlyingAsset, + IAaveIncentivesController incentivesController, + uint8 debtTokenDecimals, + string memory debtTokenName, + string memory debtTokenSymbol + ) external; +} diff --git a/contracts/interfaces/ILendingPoolConfigurator.sol b/contracts/interfaces/ILendingPoolConfigurator.sol new file mode 100644 index 00000000..8981db6c --- /dev/null +++ b/contracts/interfaces/ILendingPoolConfigurator.sol @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +interface ILendingPoolConfigurator { + struct InitReserveInput { + address aTokenImpl; + address stableDebtTokenImpl; + address variableDebtTokenImpl; + uint8 underlyingAssetDecimals; + address interestRateStrategyAddress; + address underlyingAsset; + address treasury; + address incentivesController; + string underlyingAssetName; + string aTokenName; + string aTokenSymbol; + string variableDebtTokenName; + string variableDebtTokenSymbol; + string stableDebtTokenName; + string stableDebtTokenSymbol; + } + + struct UpdateATokenInput { + address asset; + address treasury; + address incentivesController; + string name; + string symbol; + address implementation; + } + + struct UpdateDebtTokenInput { + address asset; + address incentivesController; + string name; + string symbol; + address implementation; + } + + /** + * @dev Emitted when a reserve is initialized. + * @param asset The address of the underlying asset of the reserve + * @param aToken The address of the associated aToken contract + * @param stableDebtToken The address of the associated stable rate debt token + * @param variableDebtToken The address of the associated variable rate debt token + * @param interestRateStrategyAddress The address of the interest rate strategy for the reserve + **/ + event ReserveInitialized( + address indexed asset, + address indexed aToken, + address stableDebtToken, + address variableDebtToken, + address interestRateStrategyAddress + ); + + /** + * @dev Emitted when borrowing is enabled on a reserve + * @param asset The address of the underlying asset of the reserve + * @param stableRateEnabled True if stable rate borrowing is enabled, false otherwise + **/ + event BorrowingEnabledOnReserve(address indexed asset, bool stableRateEnabled); + + /** + * @dev Emitted when borrowing is disabled on a reserve + * @param asset The address of the underlying asset of the reserve + **/ + event BorrowingDisabledOnReserve(address indexed asset); + + /** + * @dev Emitted when the collateralization risk parameters for the specified asset are updated. + * @param asset The address of the underlying asset of the reserve + * @param ltv The loan to value of the asset when used as collateral + * @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized + * @param liquidationBonus The bonus liquidators receive to liquidate this asset + **/ + event CollateralConfigurationChanged( + address indexed asset, + uint256 ltv, + uint256 liquidationThreshold, + uint256 liquidationBonus + ); + + /** + * @dev Emitted when stable rate borrowing is enabled on a reserve + * @param asset The address of the underlying asset of the reserve + **/ + event StableRateEnabledOnReserve(address indexed asset); + + /** + * @dev Emitted when stable rate borrowing is disabled on a reserve + * @param asset The address of the underlying asset of the reserve + **/ + event StableRateDisabledOnReserve(address indexed asset); + + /** + * @dev Emitted when a reserve is activated + * @param asset The address of the underlying asset of the reserve + **/ + event ReserveActivated(address indexed asset); + + /** + * @dev Emitted when a reserve is deactivated + * @param asset The address of the underlying asset of the reserve + **/ + event ReserveDeactivated(address indexed asset); + + /** + * @dev Emitted when a reserve is frozen + * @param asset The address of the underlying asset of the reserve + **/ + event ReserveFrozen(address indexed asset); + + /** + * @dev Emitted when a reserve is unfrozen + * @param asset The address of the underlying asset of the reserve + **/ + event ReserveUnfrozen(address indexed asset); + + /** + * @dev Emitted when a reserve factor is updated + * @param asset The address of the underlying asset of the reserve + * @param factor The new reserve factor + **/ + event ReserveFactorChanged(address indexed asset, uint256 factor); + + /** + * @dev Emitted when the reserve decimals are updated + * @param asset The address of the underlying asset of the reserve + * @param decimals The new decimals + **/ + event ReserveDecimalsChanged(address indexed asset, uint256 decimals); + + /** + * @dev Emitted when a reserve interest strategy contract is updated + * @param asset The address of the underlying asset of the reserve + * @param strategy The new address of the interest strategy contract + **/ + event ReserveInterestRateStrategyChanged(address indexed asset, address strategy); + + /** + * @dev Emitted when an aToken implementation is upgraded + * @param asset The address of the underlying asset of the reserve + * @param proxy The aToken proxy address + * @param implementation The new aToken implementation + **/ + event ATokenUpgraded( + address indexed asset, + address indexed proxy, + address indexed implementation + ); + + /** + * @dev Emitted when the implementation of a stable debt token is upgraded + * @param asset The address of the underlying asset of the reserve + * @param proxy The stable debt token proxy address + * @param implementation The new aToken implementation + **/ + event StableDebtTokenUpgraded( + address indexed asset, + address indexed proxy, + address indexed implementation + ); + + /** + * @dev Emitted when the implementation of a variable debt token is upgraded + * @param asset The address of the underlying asset of the reserve + * @param proxy The variable debt token proxy address + * @param implementation The new aToken implementation + **/ + event VariableDebtTokenUpgraded( + address indexed asset, + address indexed proxy, + address indexed implementation + ); +} diff --git a/contracts/interfaces/IStableDebtToken.sol b/contracts/interfaces/IStableDebtToken.sol index c24750bc..e39cf8b5 100644 --- a/contracts/interfaces/IStableDebtToken.sol +++ b/contracts/interfaces/IStableDebtToken.sol @@ -1,6 +1,9 @@ // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; +import {IInitializableDebtToken} from './IInitializableDebtToken.sol'; +import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; + /** * @title IStableDebtToken * @notice Defines the interface for the stable debt token @@ -8,7 +11,7 @@ pragma solidity 0.6.12; * @author Aave **/ -interface IStableDebtToken { +interface IStableDebtToken is IInitializableDebtToken { /** * @dev Emitted when new stable debt is minted * @param user The address of the user who triggered the minting @@ -122,4 +125,9 @@ interface IStableDebtToken { * @return The debt balance of the user since the last burn/mint action **/ function principalBalanceOf(address user) external view returns (uint256); + + /** + * @dev Returns the address of the incentives controller contract + **/ + function getIncentivesController() external view returns (IAaveIncentivesController); } diff --git a/contracts/interfaces/IUniswapV2Router02.sol b/contracts/interfaces/IUniswapV2Router02.sol new file mode 100644 index 00000000..af0f8280 --- /dev/null +++ b/contracts/interfaces/IUniswapV2Router02.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; + +interface IUniswapV2Router02 { + function swapExactTokensForTokens( + uint256 amountIn, + uint256 amountOutMin, + address[] calldata path, + address to, + uint256 deadline + ) external returns (uint256[] memory amounts); + + function swapTokensForExactTokens( + uint amountOut, + uint amountInMax, + address[] calldata path, + address to, + uint deadline + ) external returns (uint256[] memory amounts); + + function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); + + function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); +} diff --git a/contracts/interfaces/IVariableDebtToken.sol b/contracts/interfaces/IVariableDebtToken.sol index 6a0c1555..d88c25fc 100644 --- a/contracts/interfaces/IVariableDebtToken.sol +++ b/contracts/interfaces/IVariableDebtToken.sol @@ -2,13 +2,15 @@ pragma solidity 0.6.12; import {IScaledBalanceToken} from './IScaledBalanceToken.sol'; +import {IInitializableDebtToken} from './IInitializableDebtToken.sol'; +import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; /** * @title IVariableDebtToken * @author Aave * @notice Defines the basic interface for a variable debt token. **/ -interface IVariableDebtToken is IScaledBalanceToken { +interface IVariableDebtToken is IScaledBalanceToken, IInitializableDebtToken { /** * @dev Emitted after the mint action * @param from The address performing the mint @@ -52,4 +54,9 @@ interface IVariableDebtToken is IScaledBalanceToken { uint256 amount, uint256 index ) external; + + /** + * @dev Returns the address of the incentives controller contract + **/ + function getIncentivesController() external view returns (IAaveIncentivesController); } diff --git a/contracts/mocks/swap/MockUniswapV2Router02.sol b/contracts/mocks/swap/MockUniswapV2Router02.sol new file mode 100644 index 00000000..b7fd3f80 --- /dev/null +++ b/contracts/mocks/swap/MockUniswapV2Router02.sol @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; + +import {IUniswapV2Router02} from '../../interfaces/IUniswapV2Router02.sol'; +import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; +import {MintableERC20} from '../tokens/MintableERC20.sol'; + +contract MockUniswapV2Router02 is IUniswapV2Router02 { + mapping(address => uint256) internal _amountToReturn; + mapping(address => uint256) internal _amountToSwap; + mapping(address => mapping(address => mapping(uint256 => uint256))) internal _amountsIn; + mapping(address => mapping(address => mapping(uint256 => uint256))) internal _amountsOut; + uint256 internal defaultMockValue; + + function setAmountToReturn(address reserve, uint256 amount) public { + _amountToReturn[reserve] = amount; + } + + function setAmountToSwap(address reserve, uint256 amount) public { + _amountToSwap[reserve] = amount; + } + + function swapExactTokensForTokens( + uint256 amountIn, + uint256, /* amountOutMin */ + address[] calldata path, + address to, + uint256 /* deadline */ + ) external override returns (uint256[] memory amounts) { + IERC20(path[0]).transferFrom(msg.sender, address(this), amountIn); + + MintableERC20(path[1]).mint(_amountToReturn[path[0]]); + IERC20(path[1]).transfer(to, _amountToReturn[path[0]]); + + amounts = new uint256[](path.length); + amounts[0] = amountIn; + amounts[1] = _amountToReturn[path[0]]; + } + + function swapTokensForExactTokens( + uint256 amountOut, + uint256, /* amountInMax */ + address[] calldata path, + address to, + uint256 /* deadline */ + ) external override returns (uint256[] memory amounts) { + IERC20(path[0]).transferFrom(msg.sender, address(this), _amountToSwap[path[0]]); + + MintableERC20(path[1]).mint(amountOut); + IERC20(path[1]).transfer(to, amountOut); + + amounts = new uint256[](path.length); + amounts[0] = _amountToSwap[path[0]]; + amounts[1] = amountOut; + } + + function setAmountOut( + uint256 amountIn, + address reserveIn, + address reserveOut, + uint256 amountOut + ) public { + _amountsOut[reserveIn][reserveOut][amountIn] = amountOut; + } + + function setAmountIn( + uint256 amountOut, + address reserveIn, + address reserveOut, + uint256 amountIn + ) public { + _amountsIn[reserveIn][reserveOut][amountOut] = amountIn; + } + + function setDefaultMockValue(uint256 value) public { + defaultMockValue = value; + } + + function getAmountsOut(uint256 amountIn, address[] calldata path) + external + view + override + returns (uint256[] memory) + { + uint256[] memory amounts = new uint256[](path.length); + amounts[0] = amountIn; + amounts[1] = _amountsOut[path[0]][path[1]][amountIn] > 0 + ? _amountsOut[path[0]][path[1]][amountIn] + : defaultMockValue; + return amounts; + } + + function getAmountsIn(uint256 amountOut, address[] calldata path) + external + view + override + returns (uint256[] memory) + { + uint256[] memory amounts = new uint256[](path.length); + amounts[0] = _amountsIn[path[0]][path[1]][amountOut] > 0 + ? _amountsIn[path[0]][path[1]][amountOut] + : defaultMockValue; + amounts[1] = amountOut; + return amounts; + } +} diff --git a/contracts/mocks/upgradeability/MockAToken.sol b/contracts/mocks/upgradeability/MockAToken.sol index f0eda38c..7e7b6f2a 100644 --- a/contracts/mocks/upgradeability/MockAToken.sol +++ b/contracts/mocks/upgradeability/MockAToken.sol @@ -2,39 +2,11 @@ pragma solidity 0.6.12; import {AToken} from '../../protocol/tokenization/AToken.sol'; -import {LendingPool} from '../../protocol/lendingpool/LendingPool.sol'; +import {ILendingPool} from '../../interfaces/ILendingPool.sol'; +import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; contract MockAToken is AToken { - constructor( - LendingPool pool, - address underlyingAssetAddress, - address reserveTreasury, - string memory tokenName, - string memory tokenSymbol, - address incentivesController - ) - public - AToken( - pool, - underlyingAssetAddress, - reserveTreasury, - tokenName, - tokenSymbol, - incentivesController - ) - {} - function getRevision() internal pure override returns (uint256) { return 0x2; } - - function initialize( - uint8 _underlyingAssetDecimals, - string calldata _tokenName, - string calldata _tokenSymbol - ) external virtual override initializer { - _setName(_tokenName); - _setSymbol(_tokenSymbol); - _setDecimals(_underlyingAssetDecimals); - } } diff --git a/contracts/mocks/upgradeability/MockStableDebtToken.sol b/contracts/mocks/upgradeability/MockStableDebtToken.sol index 5030c171..cbc66664 100644 --- a/contracts/mocks/upgradeability/MockStableDebtToken.sol +++ b/contracts/mocks/upgradeability/MockStableDebtToken.sol @@ -4,17 +4,6 @@ pragma solidity 0.6.12; import {StableDebtToken} from '../../protocol/tokenization/StableDebtToken.sol'; contract MockStableDebtToken is StableDebtToken { - constructor( - address _pool, - address _underlyingAssetAddress, - string memory _tokenName, - string memory _tokenSymbol, - address incentivesController - ) - public - StableDebtToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol, incentivesController) - {} - function getRevision() internal pure override returns (uint256) { return 0x2; } diff --git a/contracts/mocks/upgradeability/MockVariableDebtToken.sol b/contracts/mocks/upgradeability/MockVariableDebtToken.sol index 0a9a03aa..497682c3 100644 --- a/contracts/mocks/upgradeability/MockVariableDebtToken.sol +++ b/contracts/mocks/upgradeability/MockVariableDebtToken.sol @@ -4,23 +4,6 @@ pragma solidity 0.6.12; import {VariableDebtToken} from '../../protocol/tokenization/VariableDebtToken.sol'; contract MockVariableDebtToken is VariableDebtToken { - constructor( - address _pool, - address _underlyingAssetAddress, - string memory _tokenName, - string memory _tokenSymbol, - address incentivesController - ) - public - VariableDebtToken( - _pool, - _underlyingAssetAddress, - _tokenName, - _tokenSymbol, - incentivesController - ) - {} - function getRevision() internal pure override returns (uint256) { return 0x2; } diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 7c48f237..75e80230 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -49,10 +49,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage using PercentageMath for uint256; using SafeERC20 for IERC20; - //main configuration parameters - uint256 public constant MAX_STABLE_RATE_BORROW_SIZE_PERCENT = 2500; - uint256 public constant FLASHLOAN_PREMIUM_TOTAL = 9; - uint256 public constant MAX_NUMBER_RESERVES = 128; uint256 public constant LENDINGPOOL_REVISION = 0x2; modifier whenNotPaused() { @@ -86,9 +82,20 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage * - Caching the address of the LendingPoolAddressesProvider in order to reduce gas consumption * on subsequent operations * @param provider The address of the LendingPoolAddressesProvider + * @param maxStableRateBorrowSizePercent The percentage of available liquidity that can be borrowed at once at stable rate + * @param flashLoanPremiumTotal The fee on flash loans + * @param maxNumberOfReserves Maximum number of reserves supported to be listed in this LendingPool **/ - function initialize(ILendingPoolAddressesProvider provider) public initializer { + function initialize( + ILendingPoolAddressesProvider provider, + uint256 maxStableRateBorrowSizePercent, + uint256 flashLoanPremiumTotal, + uint256 maxNumberOfReserves + ) public initializer { _addressesProvider = provider; + _maxStableRateBorrowSizePercent = maxStableRateBorrowSizePercent; + _flashLoanPremiumTotal = flashLoanPremiumTotal; + _maxNumberOfReserves = maxNumberOfReserves; } /** @@ -144,7 +151,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage address asset, uint256 amount, address to - ) external override whenNotPaused returns (uint256) { + ) external override whenNotPaused returns (uint256) { DataTypes.ReserveData storage reserve = _reserves[asset]; address aToken = reserve.aTokenAddress; @@ -499,7 +506,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage for (vars.i = 0; vars.i < assets.length; vars.i++) { aTokenAddresses[vars.i] = _reserves[assets[vars.i]].aTokenAddress; - premiums[vars.i] = amounts[vars.i].mul(FLASHLOAN_PREMIUM_TOTAL).div(10000); + premiums[vars.i] = amounts[vars.i].mul(_flashLoanPremiumTotal).div(10000); IAToken(aTokenAddresses[vars.i]).transferUnderlyingTo(receiverAddress, amounts[vars.i]); } @@ -703,6 +710,27 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage return _addressesProvider; } + /** + * @dev Returns the percentage of available liquidity that can be borrowed at once at stable rate + */ + function MAX_STABLE_RATE_BORROW_SIZE_PERCENT() public view returns (uint256) { + return _maxStableRateBorrowSizePercent; + } + + /** + * @dev Returns the fee on flash loans + */ + function FLASHLOAN_PREMIUM_TOTAL() public view returns (uint256) { + return _flashLoanPremiumTotal; + } + + /** + * @dev Returns the maximum number of reserves supported to be listed in this LendingPool + */ + function MAX_NUMBER_RESERVES() public view returns (uint256) { + return _maxNumberOfReserves; + } + /** * @dev Validates and finalizes an aToken transfer * - Only callable by the overlying aToken of the `asset` @@ -847,7 +875,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage vars.amount, amountInETH, vars.interestRateMode, - MAX_STABLE_RATE_BORROW_SIZE_PERCENT, + _maxStableRateBorrowSizePercent, _reserves, userConfig, _reservesList, @@ -909,7 +937,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage function _addReserveToList(address asset) internal { uint256 reservesCount = _reservesCount; - require(reservesCount < MAX_NUMBER_RESERVES, Errors.LP_NO_MORE_RESERVES_ALLOWED); + require(reservesCount < _maxNumberOfReserves, Errors.LP_NO_MORE_RESERVES_ALLOWED); bool reserveAlreadyAdded = _reserves[asset].id != 0 || _reservesList[0] == asset; diff --git a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol index bb3fb774..f42415ca 100644 --- a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol @@ -10,11 +10,14 @@ import { import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol'; import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; import {ILendingPool} from '../../interfaces/ILendingPool.sol'; -import {ITokenConfiguration} from '../../interfaces/ITokenConfiguration.sol'; import {IERC20Detailed} from '../../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; import {Errors} from '../libraries/helpers/Errors.sol'; import {PercentageMath} from '../libraries/math/PercentageMath.sol'; import {DataTypes} from '../libraries/types/DataTypes.sol'; +import {IInitializableDebtToken} from '../../interfaces/IInitializableDebtToken.sol'; +import {IInitializableAToken} from '../../interfaces/IInitializableAToken.sol'; +import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; +import {ILendingPoolConfigurator} from '../../interfaces/ILendingPoolConfigurator.sol'; /** * @title LendingPoolConfigurator contract @@ -22,147 +25,11 @@ import {DataTypes} from '../libraries/types/DataTypes.sol'; * @dev Implements the configuration methods for the Aave protocol **/ -contract LendingPoolConfigurator is VersionedInitializable { +contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigurator { using SafeMath for uint256; using PercentageMath for uint256; using ReserveConfiguration for DataTypes.ReserveConfigurationMap; - /** - * @dev Emitted when a reserve is initialized. - * @param asset The address of the underlying asset of the reserve - * @param aToken The address of the associated aToken contract - * @param stableDebtToken The address of the associated stable rate debt token - * @param variableDebtToken The address of the associated variable rate debt token - * @param interestRateStrategyAddress The address of the interest rate strategy for the reserve - **/ - event ReserveInitialized( - address indexed asset, - address indexed aToken, - address stableDebtToken, - address variableDebtToken, - address interestRateStrategyAddress - ); - - /** - * @dev Emitted when borrowing is enabled on a reserve - * @param asset The address of the underlying asset of the reserve - * @param stableRateEnabled True if stable rate borrowing is enabled, false otherwise - **/ - event BorrowingEnabledOnReserve(address indexed asset, bool stableRateEnabled); - - /** - * @dev Emitted when borrowing is disabled on a reserve - * @param asset The address of the underlying asset of the reserve - **/ - event BorrowingDisabledOnReserve(address indexed asset); - - /** - * @dev Emitted when the collateralization risk parameters for the specified asset are updated. - * @param asset The address of the underlying asset of the reserve - * @param ltv The loan to value of the asset when used as collateral - * @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized - * @param liquidationBonus The bonus liquidators receive to liquidate this asset - **/ - event CollateralConfigurationChanged( - address indexed asset, - uint256 ltv, - uint256 liquidationThreshold, - uint256 liquidationBonus - ); - - /** - * @dev Emitted when stable rate borrowing is enabled on a reserve - * @param asset The address of the underlying asset of the reserve - **/ - event StableRateEnabledOnReserve(address indexed asset); - - /** - * @dev Emitted when stable rate borrowing is disabled on a reserve - * @param asset The address of the underlying asset of the reserve - **/ - event StableRateDisabledOnReserve(address indexed asset); - - /** - * @dev Emitted when a reserve is activated - * @param asset The address of the underlying asset of the reserve - **/ - event ReserveActivated(address indexed asset); - - /** - * @dev Emitted when a reserve is deactivated - * @param asset The address of the underlying asset of the reserve - **/ - event ReserveDeactivated(address indexed asset); - - /** - * @dev Emitted when a reserve is frozen - * @param asset The address of the underlying asset of the reserve - **/ - event ReserveFrozen(address indexed asset); - - /** - * @dev Emitted when a reserve is unfrozen - * @param asset The address of the underlying asset of the reserve - **/ - event ReserveUnfrozen(address indexed asset); - - /** - * @dev Emitted when a reserve factor is updated - * @param asset The address of the underlying asset of the reserve - * @param factor The new reserve factor - **/ - event ReserveFactorChanged(address indexed asset, uint256 factor); - - /** - * @dev Emitted when the reserve decimals are updated - * @param asset The address of the underlying asset of the reserve - * @param decimals The new decimals - **/ - event ReserveDecimalsChanged(address indexed asset, uint256 decimals); - - /** - * @dev Emitted when a reserve interest strategy contract is updated - * @param asset The address of the underlying asset of the reserve - * @param strategy The new address of the interest strategy contract - **/ - event ReserveInterestRateStrategyChanged(address indexed asset, address strategy); - - /** - * @dev Emitted when an aToken implementation is upgraded - * @param asset The address of the underlying asset of the reserve - * @param proxy The aToken proxy address - * @param implementation The new aToken implementation - **/ - event ATokenUpgraded( - address indexed asset, - address indexed proxy, - address indexed implementation - ); - - /** - * @dev Emitted when the implementation of a stable debt token is upgraded - * @param asset The address of the underlying asset of the reserve - * @param proxy The stable debt token proxy address - * @param implementation The new aToken implementation - **/ - event StableDebtTokenUpgraded( - address indexed asset, - address indexed proxy, - address indexed implementation - ); - - /** - * @dev Emitted when the implementation of a variable debt token is upgraded - * @param asset The address of the underlying asset of the reserve - * @param proxy The variable debt token proxy address - * @param implementation The new aToken implementation - **/ - event VariableDebtTokenUpgraded( - address indexed asset, - address indexed proxy, - address indexed implementation - ); - ILendingPoolAddressesProvider internal addressesProvider; ILendingPool internal pool; @@ -191,114 +58,186 @@ contract LendingPoolConfigurator is VersionedInitializable { } /** - * @dev Initializes a reserve - * @param aTokenImpl The address of the aToken contract implementation - * @param stableDebtTokenImpl The address of the stable debt token contract - * @param variableDebtTokenImpl The address of the variable debt token contract - * @param underlyingAssetDecimals The decimals of the reserve underlying asset - * @param interestRateStrategyAddress The address of the interest rate strategy contract for this reserve + * @dev Initializes reserves in batch **/ - function initReserve( - address aTokenImpl, - address stableDebtTokenImpl, - address variableDebtTokenImpl, - uint8 underlyingAssetDecimals, - address interestRateStrategyAddress - ) public onlyPoolAdmin { - address asset = ITokenConfiguration(aTokenImpl).UNDERLYING_ASSET_ADDRESS(); + function batchInitReserve(InitReserveInput[] calldata inputParams) public onlyPoolAdmin { + ILendingPool cachedPool = pool; + for (uint256 i = 0; i < inputParams.length; i++) { + _initReserve(cachedPool, inputParams[i]); + } + } - require( - address(pool) == ITokenConfiguration(aTokenImpl).POOL(), - Errors.LPC_INVALID_ATOKEN_POOL_ADDRESS - ); - require( - address(pool) == ITokenConfiguration(stableDebtTokenImpl).POOL(), - Errors.LPC_INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS - ); - require( - address(pool) == ITokenConfiguration(variableDebtTokenImpl).POOL(), - Errors.LPC_INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS - ); - require( - asset == ITokenConfiguration(stableDebtTokenImpl).UNDERLYING_ASSET_ADDRESS(), - Errors.LPC_INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS - ); - require( - asset == ITokenConfiguration(variableDebtTokenImpl).UNDERLYING_ASSET_ADDRESS(), - Errors.LPC_INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS - ); - - address aTokenProxyAddress = _initTokenWithProxy(aTokenImpl, underlyingAssetDecimals); + function _initReserve(ILendingPool pool, InitReserveInput calldata inputParams) internal { + address aTokenProxyAddress = + _initTokenWithProxy( + inputParams.aTokenImpl, + abi.encodeWithSelector( + IInitializableAToken.initialize.selector, + pool, + inputParams.treasury, + inputParams.underlyingAsset, + IAaveIncentivesController(inputParams.incentivesController), + inputParams.underlyingAssetDecimals, + inputParams.aTokenName, + inputParams.aTokenSymbol + ) + ); address stableDebtTokenProxyAddress = - _initTokenWithProxy(stableDebtTokenImpl, underlyingAssetDecimals); + _initTokenWithProxy( + inputParams.stableDebtTokenImpl, + abi.encodeWithSelector( + IInitializableDebtToken.initialize.selector, + pool, + inputParams.underlyingAsset, + IAaveIncentivesController(inputParams.incentivesController), + inputParams.underlyingAssetDecimals, + inputParams.stableDebtTokenName, + inputParams.stableDebtTokenSymbol + ) + ); address variableDebtTokenProxyAddress = - _initTokenWithProxy(variableDebtTokenImpl, underlyingAssetDecimals); + _initTokenWithProxy( + inputParams.variableDebtTokenImpl, + abi.encodeWithSelector( + IInitializableDebtToken.initialize.selector, + pool, + inputParams.underlyingAsset, + IAaveIncentivesController(inputParams.incentivesController), + inputParams.underlyingAssetDecimals, + inputParams.variableDebtTokenName, + inputParams.variableDebtTokenSymbol + ) + ); pool.initReserve( - asset, + inputParams.underlyingAsset, aTokenProxyAddress, stableDebtTokenProxyAddress, variableDebtTokenProxyAddress, - interestRateStrategyAddress + inputParams.interestRateStrategyAddress ); - DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + DataTypes.ReserveConfigurationMap memory currentConfig = + pool.getConfiguration(inputParams.underlyingAsset); - currentConfig.setDecimals(underlyingAssetDecimals); + currentConfig.setDecimals(inputParams.underlyingAssetDecimals); currentConfig.setActive(true); currentConfig.setFrozen(false); - pool.setConfiguration(asset, currentConfig.data); + pool.setConfiguration(inputParams.underlyingAsset, currentConfig.data); emit ReserveInitialized( - asset, + inputParams.underlyingAsset, aTokenProxyAddress, stableDebtTokenProxyAddress, variableDebtTokenProxyAddress, - interestRateStrategyAddress + inputParams.interestRateStrategyAddress ); } /** * @dev Updates the aToken implementation for the reserve - * @param asset The address of the underlying asset of the reserve to be updated - * @param implementation The address of the new aToken implementation **/ - function updateAToken(address asset, address implementation) external onlyPoolAdmin { - DataTypes.ReserveData memory reserveData = pool.getReserveData(asset); + function updateAToken(UpdateATokenInput calldata inputParams) external onlyPoolAdmin { + ILendingPool cachedPool = pool; - _upgradeTokenImplementation(asset, reserveData.aTokenAddress, implementation); + DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(inputParams.asset); - emit ATokenUpgraded(asset, reserveData.aTokenAddress, implementation); + DataTypes.ReserveConfigurationMap memory configuration = + cachedPool.getConfiguration(inputParams.asset); + + (, , , uint256 decimals, ) = configuration.getParamsMemory(); + + _upgradeTokenImplementation( + reserveData.aTokenAddress, + inputParams.implementation, + abi.encodeWithSelector( + IInitializableAToken.initialize.selector, + cachedPool, + inputParams.treasury, + inputParams.asset, + inputParams.incentivesController, + decimals, + inputParams.name, + inputParams.symbol + ) + ); + + emit ATokenUpgraded(inputParams.asset, reserveData.aTokenAddress, inputParams.implementation); } /** * @dev Updates the stable debt token implementation for the reserve - * @param asset The address of the underlying asset of the reserve to be updated - * @param implementation The address of the new aToken implementation **/ - function updateStableDebtToken(address asset, address implementation) external onlyPoolAdmin { - DataTypes.ReserveData memory reserveData = pool.getReserveData(asset); + function updateStableDebtToken(UpdateDebtTokenInput calldata inputParams) external onlyPoolAdmin { + ILendingPool cachedPool = pool; - _upgradeTokenImplementation(asset, reserveData.stableDebtTokenAddress, implementation); + DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(inputParams.asset); - emit StableDebtTokenUpgraded(asset, reserveData.stableDebtTokenAddress, implementation); + DataTypes.ReserveConfigurationMap memory configuration = + cachedPool.getConfiguration(inputParams.asset); + + (, , , uint256 decimals, ) = configuration.getParamsMemory(); + + _upgradeTokenImplementation( + reserveData.stableDebtTokenAddress, + inputParams.implementation, + abi.encodeWithSelector( + IInitializableDebtToken.initialize.selector, + cachedPool, + inputParams.asset, + inputParams.incentivesController, + decimals, + inputParams.name, + inputParams.symbol + ) + ); + + emit StableDebtTokenUpgraded( + inputParams.asset, + reserveData.stableDebtTokenAddress, + inputParams.implementation + ); } /** * @dev Updates the variable debt token implementation for the asset - * @param asset The address of the underlying asset of the reserve to be updated - * @param implementation The address of the new aToken implementation **/ - function updateVariableDebtToken(address asset, address implementation) external onlyPoolAdmin { - DataTypes.ReserveData memory reserveData = pool.getReserveData(asset); + function updateVariableDebtToken(UpdateDebtTokenInput calldata inputParams) + external + onlyPoolAdmin + { + ILendingPool cachedPool = pool; - _upgradeTokenImplementation(asset, reserveData.variableDebtTokenAddress, implementation); + DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(inputParams.asset); - emit VariableDebtTokenUpgraded(asset, reserveData.variableDebtTokenAddress, implementation); + DataTypes.ReserveConfigurationMap memory configuration = + cachedPool.getConfiguration(inputParams.asset); + + (, , , uint256 decimals, ) = configuration.getParamsMemory(); + + _upgradeTokenImplementation( + reserveData.variableDebtTokenAddress, + inputParams.implementation, + abi.encodeWithSelector( + IInitializableDebtToken.initialize.selector, + cachedPool, + inputParams.asset, + inputParams.incentivesController, + decimals, + inputParams.name, + inputParams.symbol + ) + ); + + emit VariableDebtTokenUpgraded( + inputParams.asset, + reserveData.variableDebtTokenAddress, + inputParams.implementation + ); } /** @@ -509,44 +448,27 @@ contract LendingPoolConfigurator is VersionedInitializable { pool.setPause(val); } - function _initTokenWithProxy(address implementation, uint8 decimals) internal returns (address) { + function _initTokenWithProxy(address implementation, bytes memory initParams) + internal + returns (address) + { InitializableImmutableAdminUpgradeabilityProxy proxy = new InitializableImmutableAdminUpgradeabilityProxy(address(this)); - bytes memory params = - abi.encodeWithSignature( - 'initialize(uint8,string,string)', - decimals, - IERC20Detailed(implementation).name(), - IERC20Detailed(implementation).symbol() - ); - - proxy.initialize(implementation, params); + proxy.initialize(implementation, initParams); return address(proxy); } function _upgradeTokenImplementation( - address asset, address proxyAddress, - address implementation + address implementation, + bytes memory initParams ) internal { InitializableImmutableAdminUpgradeabilityProxy proxy = InitializableImmutableAdminUpgradeabilityProxy(payable(proxyAddress)); - DataTypes.ReserveConfigurationMap memory configuration = pool.getConfiguration(asset); - - (, , , uint256 decimals, ) = configuration.getParamsMemory(); - - bytes memory params = - abi.encodeWithSignature( - 'initialize(uint8,string,string)', - uint8(decimals), - IERC20Detailed(implementation).name(), - IERC20Detailed(implementation).symbol() - ); - - proxy.upgradeToAndCall(implementation, params); + proxy.upgradeToAndCall(implementation, initParams); } function _checkNoLiquidity(address asset) internal view { diff --git a/contracts/protocol/lendingpool/LendingPoolStorage.sol b/contracts/protocol/lendingpool/LendingPoolStorage.sol index 4edff4a3..198a3eea 100644 --- a/contracts/protocol/lendingpool/LendingPoolStorage.sol +++ b/contracts/protocol/lendingpool/LendingPoolStorage.sol @@ -23,4 +23,10 @@ contract LendingPoolStorage { uint256 internal _reservesCount; bool internal _paused; + + uint256 internal _maxStableRateBorrowSizePercent; + + uint256 internal _flashLoanPremiumTotal; + + uint256 internal _maxNumberOfReserves; } diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index d08e7055..080b792d 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -89,20 +89,13 @@ library ValidationLogic { } struct ValidateBorrowLocalVars { - uint256 principalBorrowBalance; uint256 currentLtv; uint256 currentLiquidationThreshold; - uint256 requestedBorrowAmountETH; uint256 amountOfCollateralNeededETH; uint256 userCollateralBalanceETH; uint256 userBorrowBalanceETH; - uint256 borrowBalanceIncrease; - uint256 currentReserveStableRate; uint256 availableLiquidity; - uint256 finalUserBorrowRate; uint256 healthFactor; - DataTypes.InterestRateMode rateMode; - bool healthFactorBelowThreshold; bool isActive; bool isFrozen; bool borrowingEnabled; @@ -197,7 +190,7 @@ library ValidationLogic { * 3. Users will be able to borrow only a portion of the total available liquidity **/ - if (vars.rateMode == DataTypes.InterestRateMode.STABLE) { + if (interestRateMode == uint256(DataTypes.InterestRateMode.STABLE)) { //check if the borrow mode is stable and if stable rate borrowing is enabled on this reserve require(vars.stableRateBorrowingEnabled, Errors.VL_STABLE_BORROWING_NOT_ENABLED); diff --git a/contracts/protocol/tokenization/AToken.sol b/contracts/protocol/tokenization/AToken.sol index 00df0b61..1a47ebf4 100644 --- a/contracts/protocol/tokenization/AToken.sol +++ b/contracts/protocol/tokenization/AToken.sol @@ -9,13 +9,18 @@ import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {Errors} from '../libraries/helpers/Errors.sol'; import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol'; import {IncentivizedERC20} from './IncentivizedERC20.sol'; +import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; /** * @title Aave ERC20 AToken * @dev Implementation of the interest bearing token for the Aave protocol * @author Aave */ -contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { +contract AToken is + VersionedInitializable, + IncentivizedERC20('ATOKEN_IMPL', 'ATOKEN_IMPL', 0), + IAToken +{ using WadRayMath for uint256; using SafeERC20 for IERC20; @@ -25,44 +30,46 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { bytes32 public constant PERMIT_TYPEHASH = keccak256('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)'); - uint256 public constant UINT_MAX_VALUE = uint256(-1); uint256 public constant ATOKEN_REVISION = 0x1; - address public immutable UNDERLYING_ASSET_ADDRESS; - address public immutable RESERVE_TREASURY_ADDRESS; - ILendingPool public immutable POOL; /// @dev owner => next valid nonce to submit with permit() mapping(address => uint256) public _nonces; bytes32 public DOMAIN_SEPARATOR; - modifier onlyLendingPool { - require(_msgSender() == address(POOL), Errors.CT_CALLER_MUST_BE_LENDING_POOL); - _; - } + ILendingPool internal _pool; + address internal _treasury; + address internal _underlyingAsset; + IAaveIncentivesController internal _incentivesController; - constructor( - ILendingPool pool, - address underlyingAssetAddress, - address reserveTreasuryAddress, - string memory tokenName, - string memory tokenSymbol, - address incentivesController - ) public IncentivizedERC20(tokenName, tokenSymbol, 18, incentivesController) { - POOL = pool; - UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress; - RESERVE_TREASURY_ADDRESS = reserveTreasuryAddress; + modifier onlyLendingPool { + require(_msgSender() == address(_pool), Errors.CT_CALLER_MUST_BE_LENDING_POOL); + _; } function getRevision() internal pure virtual override returns (uint256) { return ATOKEN_REVISION; } + /** + * @dev Initializes the aToken + * @param pool The address of the lending pool where this aToken will be used + * @param treasury The address of the Aave treasury, receiving the fees on this aToken + * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) + * @param incentivesController The smart contract managing potential incentives distribution + * @param aTokenDecimals The decimals of the aToken, same as the underlying asset's + * @param aTokenName The name of the aToken + * @param aTokenSymbol The symbol of the aToken + */ function initialize( - uint8 underlyingAssetDecimals, - string calldata tokenName, - string calldata tokenSymbol - ) external virtual initializer { + ILendingPool pool, + address treasury, + address underlyingAsset, + IAaveIncentivesController incentivesController, + uint8 aTokenDecimals, + string calldata aTokenName, + string calldata aTokenSymbol + ) external override initializer { uint256 chainId; //solium-disable-next-line @@ -73,16 +80,21 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { DOMAIN_SEPARATOR = keccak256( abi.encode( EIP712_DOMAIN, - keccak256(bytes(tokenName)), + keccak256(bytes(aTokenName)), keccak256(EIP712_REVISION), chainId, address(this) ) ); - _setName(tokenName); - _setSymbol(tokenSymbol); - _setDecimals(underlyingAssetDecimals); + _setName(aTokenName); + _setSymbol(aTokenSymbol); + _setDecimals(aTokenDecimals); + + _pool = pool; + _treasury = treasury; + _underlyingAsset = underlyingAsset; + _incentivesController = incentivesController; } /** @@ -103,7 +115,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { require(amountScaled != 0, Errors.CT_INVALID_BURN_AMOUNT); _burn(user, amountScaled); - IERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(receiverOfUnderlying, amount); + IERC20(_underlyingAsset).safeTransfer(receiverOfUnderlying, amount); emit Transfer(user, address(0), amount); emit Burn(user, receiverOfUnderlying, amount, index); @@ -145,14 +157,16 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { return; } + address treasury = _treasury; + // Compared to the normal mint, we don't check for rounding errors. // The amount to mint can easily be very small since it is a fraction of the interest ccrued. // In that case, the treasury will experience a (very small) loss, but it // wont cause potentially valid transactions to fail. - _mint(RESERVE_TREASURY_ADDRESS, amount.rayDiv(index)); + _mint(treasury, amount.rayDiv(index)); - emit Transfer(address(0), RESERVE_TREASURY_ADDRESS, amount); - emit Mint(RESERVE_TREASURY_ADDRESS, amount, index); + emit Transfer(address(0), treasury, amount); + emit Mint(treasury, amount, index); } /** @@ -185,7 +199,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { override(IncentivizedERC20, IERC20) returns (uint256) { - return super.balanceOf(user).rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS)); + return super.balanceOf(user).rayMul(_pool.getReserveNormalizedIncome(_underlyingAsset)); } /** @@ -226,7 +240,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { return 0; } - return currentSupplyScaled.rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS)); + return currentSupplyScaled.rayMul(_pool.getReserveNormalizedIncome(_underlyingAsset)); } /** @@ -237,6 +251,41 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { return super.totalSupply(); } + /** + * @dev Returns the address of the Aave treasury, receiving the fees on this aToken + **/ + function RESERVE_TREASURY_ADDRESS() public view returns (address) { + return _treasury; + } + + /** + * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) + **/ + function UNDERLYING_ASSET_ADDRESS() public view returns (address) { + return _underlyingAsset; + } + + /** + * @dev Returns the address of the lending pool where this aToken is used + **/ + function POOL() public view returns (ILendingPool) { + return _pool; + } + + /** + * @dev For internal usage in the logic of the parent contract IncentivizedERC20 + **/ + function _getIncentivesController() internal view override returns (IAaveIncentivesController) { + return _incentivesController; + } + + /** + * @dev Returns the address of the incentives controller contract + **/ + function getIncentivesController() external view override returns (IAaveIncentivesController) { + return _getIncentivesController(); + } + /** * @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer * assets in borrow(), withdraw() and flashLoan() @@ -250,7 +299,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { onlyLendingPool returns (uint256) { - IERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(target, amount); + IERC20(_underlyingAsset).safeTransfer(target, amount); return amount; } @@ -305,7 +354,10 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { uint256 amount, bool validate ) internal { - uint256 index = POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS); + address underlyingAsset = _underlyingAsset; + ILendingPool pool = _pool; + + uint256 index = pool.getReserveNormalizedIncome(underlyingAsset); uint256 fromBalanceBefore = super.balanceOf(from).rayMul(index); uint256 toBalanceBefore = super.balanceOf(to).rayMul(index); @@ -313,14 +365,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { super._transfer(from, to, amount.rayDiv(index)); if (validate) { - POOL.finalizeTransfer( - UNDERLYING_ASSET_ADDRESS, - from, - to, - amount, - fromBalanceBefore, - toBalanceBefore - ); + pool.finalizeTransfer(underlyingAsset, from, to, amount, fromBalanceBefore, toBalanceBefore); } emit BalanceTransfer(from, to, amount, index); diff --git a/contracts/protocol/tokenization/DelegationAwareAToken.sol b/contracts/protocol/tokenization/DelegationAwareAToken.sol index 4e49f2b6..443e10fb 100644 --- a/contracts/protocol/tokenization/DelegationAwareAToken.sol +++ b/contracts/protocol/tokenization/DelegationAwareAToken.sol @@ -14,36 +14,17 @@ import {AToken} from './AToken.sol'; contract DelegationAwareAToken is AToken { modifier onlyPoolAdmin { require( - _msgSender() == ILendingPool(POOL).getAddressesProvider().getPoolAdmin(), + _msgSender() == ILendingPool(_pool).getAddressesProvider().getPoolAdmin(), Errors.CALLER_NOT_POOL_ADMIN ); _; } - constructor( - ILendingPool pool, - address underlyingAssetAddress, - address reserveTreasury, - string memory tokenName, - string memory tokenSymbol, - address incentivesController - ) - public - AToken( - pool, - underlyingAssetAddress, - reserveTreasury, - tokenName, - tokenSymbol, - incentivesController - ) - {} - /** * @dev Delegates voting power of the underlying asset to a `delegatee` address * @param delegatee The address that will receive the delegation **/ function delegateUnderlyingTo(address delegatee) external onlyPoolAdmin { - IDelegationToken(UNDERLYING_ASSET_ADDRESS).delegate(delegatee); + IDelegationToken(_underlyingAsset).delegate(delegatee); } } diff --git a/contracts/protocol/tokenization/IncentivizedERC20.sol b/contracts/protocol/tokenization/IncentivizedERC20.sol index 101eaf9a..fb831769 100644 --- a/contracts/protocol/tokenization/IncentivizedERC20.sol +++ b/contracts/protocol/tokenization/IncentivizedERC20.sol @@ -12,11 +12,9 @@ import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesControl * @notice Basic ERC20 implementation * @author Aave, inspired by the Openzeppelin ERC20 implementation **/ -contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { +abstract contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { using SafeMath for uint256; - IAaveIncentivesController internal immutable _incentivesController; - mapping(address => uint256) internal _balances; mapping(address => mapping(address => uint256)) private _allowances; @@ -28,13 +26,11 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { constructor( string memory name, string memory symbol, - uint8 decimals, - address incentivesController + uint8 decimals ) public { _name = name; _symbol = symbol; _decimals = decimals; - _incentivesController = IAaveIncentivesController(incentivesController); } /** @@ -72,6 +68,12 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { return _balances[account]; } + /** + * @return Abstract function implemented by the child aToken/debtToken. + * Done this way in order to not break compatibility with previous versions of aTokens/debtTokens + **/ + function _getIncentivesController() internal view virtual returns(IAaveIncentivesController); + /** * @dev Executes a transfer of tokens from _msgSender() to recipient * @param recipient The recipient of the tokens @@ -180,11 +182,11 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { uint256 oldRecipientBalance = _balances[recipient]; _balances[recipient] = _balances[recipient].add(amount); - if (address(_incentivesController) != address(0)) { + if (address(_getIncentivesController()) != address(0)) { uint256 currentTotalSupply = _totalSupply; - _incentivesController.handleAction(sender, currentTotalSupply, oldSenderBalance); + _getIncentivesController().handleAction(sender, currentTotalSupply, oldSenderBalance); if (sender != recipient) { - _incentivesController.handleAction(recipient, currentTotalSupply, oldRecipientBalance); + _getIncentivesController().handleAction(recipient, currentTotalSupply, oldRecipientBalance); } } } @@ -200,8 +202,8 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { uint256 oldAccountBalance = _balances[account]; _balances[account] = oldAccountBalance.add(amount); - if (address(_incentivesController) != address(0)) { - _incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance); + if (address(_getIncentivesController()) != address(0)) { + _getIncentivesController().handleAction(account, oldTotalSupply, oldAccountBalance); } } @@ -216,8 +218,8 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { uint256 oldAccountBalance = _balances[account]; _balances[account] = oldAccountBalance.sub(amount, 'ERC20: burn amount exceeds balance'); - if (address(_incentivesController) != address(0)) { - _incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance); + if (address(_getIncentivesController()) != address(0)) { + _getIncentivesController().handleAction(account, oldTotalSupply, oldAccountBalance); } } diff --git a/contracts/protocol/tokenization/StableDebtToken.sol b/contracts/protocol/tokenization/StableDebtToken.sol index 78401405..f52c4931 100644 --- a/contracts/protocol/tokenization/StableDebtToken.sol +++ b/contracts/protocol/tokenization/StableDebtToken.sol @@ -5,6 +5,8 @@ import {DebtTokenBase} from './base/DebtTokenBase.sol'; import {MathUtils} from '../libraries/math/MathUtils.sol'; import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {IStableDebtToken} from '../../interfaces/IStableDebtToken.sol'; +import {ILendingPool} from '../../interfaces/ILendingPool.sol'; +import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; import {Errors} from '../libraries/helpers/Errors.sol'; /** @@ -23,13 +25,35 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { mapping(address => uint256) internal _usersStableRate; uint40 internal _totalSupplyTimestamp; - constructor( - address pool, + ILendingPool internal _pool; + address internal _underlyingAsset; + IAaveIncentivesController internal _incentivesController; + + /** + * @dev Initializes the debt token. + * @param pool The address of the lending pool where this aToken will be used + * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) + * @param incentivesController The smart contract managing potential incentives distribution + * @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's + * @param debtTokenName The name of the token + * @param debtTokenSymbol The symbol of the token + */ + function initialize( + ILendingPool pool, address underlyingAsset, - string memory name, - string memory symbol, - address incentivesController - ) public DebtTokenBase(pool, underlyingAsset, name, symbol, incentivesController) {} + IAaveIncentivesController incentivesController, + uint8 debtTokenDecimals, + string memory debtTokenName, + string memory debtTokenSymbol + ) public override initializer { + _setName(debtTokenName); + _setSymbol(debtTokenSymbol); + _setDecimals(debtTokenDecimals); + + _pool = pool; + _underlyingAsset = underlyingAsset; + _incentivesController = incentivesController; + } /** * @dev Gets the revision of the stable debt token implementation @@ -300,6 +324,48 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { return super.balanceOf(user); } + /** + * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) + **/ + function UNDERLYING_ASSET_ADDRESS() public view returns (address) { + return _underlyingAsset; + } + + /** + * @dev Returns the address of the lending pool where this aToken is used + **/ + function POOL() public view returns (ILendingPool) { + return _pool; + } + + /** + * @dev Returns the address of the incentives controller contract + **/ + function getIncentivesController() external view override returns (IAaveIncentivesController) { + return _getIncentivesController(); + } + + /** + * @dev For internal usage in the logic of the parent contracts + **/ + function _getIncentivesController() internal view override returns (IAaveIncentivesController) { + return _incentivesController; + } + + /** + * @dev For internal usage in the logic of the parent contracts + **/ + function _getUnderlyingAssetAddress() internal view override returns (address) { + return _underlyingAsset; + } + + /** + * @dev For internal usage in the logic of the parent contracts + **/ + function _getLendingPool() internal view override returns (ILendingPool) { + return _pool; + } + /** * @dev Calculates the total supply * @param avgRate The average rate at which the total supply increases diff --git a/contracts/protocol/tokenization/VariableDebtToken.sol b/contracts/protocol/tokenization/VariableDebtToken.sol index d2e27ac3..60a47e12 100644 --- a/contracts/protocol/tokenization/VariableDebtToken.sol +++ b/contracts/protocol/tokenization/VariableDebtToken.sol @@ -5,6 +5,8 @@ import {IVariableDebtToken} from '../../interfaces/IVariableDebtToken.sol'; import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {Errors} from '../libraries/helpers/Errors.sol'; import {DebtTokenBase} from './base/DebtTokenBase.sol'; +import {ILendingPool} from '../../interfaces/ILendingPool.sol'; +import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; /** * @title VariableDebtToken @@ -17,13 +19,35 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { uint256 public constant DEBT_TOKEN_REVISION = 0x1; - constructor( - address pool, + ILendingPool internal _pool; + address internal _underlyingAsset; + IAaveIncentivesController internal _incentivesController; + + /** + * @dev Initializes the debt token. + * @param pool The address of the lending pool where this aToken will be used + * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) + * @param incentivesController The smart contract managing potential incentives distribution + * @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's + * @param debtTokenName The name of the token + * @param debtTokenSymbol The symbol of the token + */ + function initialize( + ILendingPool pool, address underlyingAsset, - string memory name, - string memory symbol, - address incentivesController - ) public DebtTokenBase(pool, underlyingAsset, name, symbol, incentivesController) {} + IAaveIncentivesController incentivesController, + uint8 debtTokenDecimals, + string memory debtTokenName, + string memory debtTokenSymbol + ) public override initializer { + _setName(debtTokenName); + _setSymbol(debtTokenSymbol); + _setDecimals(debtTokenDecimals); + + _pool = pool; + _underlyingAsset = underlyingAsset; + _incentivesController = incentivesController; + } /** * @dev Gets the revision of the stable debt token implementation @@ -44,7 +68,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { return 0; } - return scaledBalance.rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS)); + return scaledBalance.rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAsset)); } /** @@ -113,8 +137,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { * @return The total supply **/ function totalSupply() public view virtual override returns (uint256) { - return - super.totalSupply().rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS)); + return super.totalSupply().rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAsset)); } /** @@ -139,4 +162,37 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { { return (super.balanceOf(user), super.totalSupply()); } + + /** + * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) + **/ + function UNDERLYING_ASSET_ADDRESS() public view returns (address) { + return _underlyingAsset; + } + + /** + * @dev Returns the address of the incentives controller contract + **/ + function getIncentivesController() external view override returns (IAaveIncentivesController) { + return _getIncentivesController(); + } + + /** + * @dev Returns the address of the lending pool where this aToken is used + **/ + function POOL() public view returns (ILendingPool) { + return _pool; + } + + function _getIncentivesController() internal view override returns (IAaveIncentivesController) { + return _incentivesController; + } + + function _getUnderlyingAssetAddress() internal view override returns (address) { + return _underlyingAsset; + } + + function _getLendingPool() internal view override returns (ILendingPool) { + return _pool; + } } diff --git a/contracts/protocol/tokenization/base/DebtTokenBase.sol b/contracts/protocol/tokenization/base/DebtTokenBase.sol index 07bdef22..4d75bc2f 100644 --- a/contracts/protocol/tokenization/base/DebtTokenBase.sol +++ b/contracts/protocol/tokenization/base/DebtTokenBase.sol @@ -16,54 +16,20 @@ import {Errors} from '../../libraries/helpers/Errors.sol'; */ abstract contract DebtTokenBase is - IncentivizedERC20, + IncentivizedERC20('DEBTTOKEN_IMPL', 'DEBTTOKEN_IMPL', 0), VersionedInitializable, ICreditDelegationToken { - address public immutable UNDERLYING_ASSET_ADDRESS; - ILendingPool public immutable POOL; - mapping(address => mapping(address => uint256)) internal _borrowAllowances; /** * @dev Only lending pool can call functions marked by this modifier **/ modifier onlyLendingPool { - require(_msgSender() == address(POOL), Errors.CT_CALLER_MUST_BE_LENDING_POOL); + require(_msgSender() == address(_getLendingPool()), Errors.CT_CALLER_MUST_BE_LENDING_POOL); _; } - /** - * @dev The metadata of the token will be set on the proxy, that the reason of - * passing "NULL" and 0 as metadata - */ - constructor( - address pool, - address underlyingAssetAddress, - string memory name, - string memory symbol, - address incentivesController - ) public IncentivizedERC20(name, symbol, 18, incentivesController) { - POOL = ILendingPool(pool); - UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress; - } - - /** - * @dev Initializes the debt token. - * @param name The name of the token - * @param symbol The symbol of the token - * @param decimals The decimals of the token - */ - function initialize( - uint8 decimals, - string memory name, - string memory symbol - ) public initializer { - _setName(name); - _setSymbol(symbol); - _setDecimals(decimals); - } - /** * @dev delegates borrowing power to a user on the specific debt token * @param delegatee the address receiving the delegated borrowing power @@ -73,7 +39,7 @@ abstract contract DebtTokenBase is **/ function approveDelegation(address delegatee, uint256 amount) external override { _borrowAllowances[_msgSender()][delegatee] = amount; - emit BorrowAllowanceDelegated(_msgSender(), delegatee, UNDERLYING_ASSET_ADDRESS, amount); + emit BorrowAllowanceDelegated(_msgSender(), delegatee, _getUnderlyingAssetAddress(), amount); } /** @@ -162,6 +128,10 @@ abstract contract DebtTokenBase is _borrowAllowances[delegator][delegatee] = newAllowance; - emit BorrowAllowanceDelegated(delegator, delegatee, UNDERLYING_ASSET_ADDRESS, newAllowance); + emit BorrowAllowanceDelegated(delegator, delegatee, _getUnderlyingAssetAddress(), newAllowance); } + + function _getUnderlyingAssetAddress() internal view virtual returns (address); + + function _getLendingPool() internal view virtual returns (ILendingPool); } From 517d51f900bb6cdef41ee879dbc5c358e9070bf6 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 29 Jan 2021 22:52:12 -0500 Subject: [PATCH 051/219] Began work on implementing light deployment scripts --- helpers/contracts-deployments.ts | 14 ++--- helpers/init-helpers.ts | 93 ++++++++++++++++++++++-------- markets/uniswap/reservesConfigs.ts | 2 +- 3 files changed, 77 insertions(+), 32 deletions(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 8f7f0c9d..1e5940eb 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -300,7 +300,7 @@ export const deployStableDebtToken = async ( verify: boolean ) => withSaveAndVerify( - await new StableDebtTokenFactory(await getFirstSigner()).deploy(...args), + await new StableDebtTokenFactory(await getFirstSigner()).deploy(), eContractid.StableDebtToken, args, verify @@ -311,7 +311,7 @@ export const deployVariableDebtToken = async ( verify: boolean ) => withSaveAndVerify( - await new VariableDebtTokenFactory(await getFirstSigner()).deploy(...args), + await new VariableDebtTokenFactory(await getFirstSigner()).deploy(), eContractid.VariableDebtToken, args, verify @@ -338,7 +338,7 @@ export const deployGenericAToken = async ( ] = [poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController]; return withSaveAndVerify( - await new ATokenFactory(await getFirstSigner()).deploy(...args), + await new ATokenFactory(await getFirstSigner()).deploy(), eContractid.AToken, args, verify @@ -366,7 +366,7 @@ export const deployDelegationAwareAToken = async ( ] = [poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController]; return withSaveAndVerify( - await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(...args), + await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(), eContractid.DelegationAwareAToken, args, verify @@ -451,7 +451,7 @@ export const deployMockStableDebtToken = async ( verify?: boolean ) => withSaveAndVerify( - await new MockStableDebtTokenFactory(await getFirstSigner()).deploy(...args), + await new MockStableDebtTokenFactory(await getFirstSigner()).deploy(), eContractid.MockStableDebtToken, args, verify @@ -470,7 +470,7 @@ export const deployMockVariableDebtToken = async ( verify?: boolean ) => withSaveAndVerify( - await new MockVariableDebtTokenFactory(await getFirstSigner()).deploy(...args), + await new MockVariableDebtTokenFactory(await getFirstSigner()).deploy(), eContractid.MockVariableDebtToken, args, verify @@ -481,7 +481,7 @@ export const deployMockAToken = async ( verify?: boolean ) => withSaveAndVerify( - await new MockATokenFactory(await getFirstSigner()).deploy(...args), + await new MockATokenFactory(await getFirstSigner()).deploy(), eContractid.MockAToken, args, verify diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 2083e0df..a8794df2 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -95,7 +95,19 @@ export const initReservesByHelper = async ( BigNumberish ][] = []; const reservesDecimals: string[] = []; - + // TEST + const inputParams: { + asset: string, + rates: [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish + ] + }[] = []; + // TEST for (let [assetSymbol, { reserveDecimals }] of reservesChunk) { const assetAddressIndex = Object.keys(tokenAddresses).findIndex( (value) => value === assetSymbol @@ -130,12 +142,26 @@ export const initReservesByHelper = async ( stableRateSlope2, ]); reservesDecimals.push(reserveDecimals); + + // TEST + inputParams.push({ + asset: tokenAddress, + rates: [ + optimalUtilizationRate, + baseVariableBorrowRate, + variableRateSlope1, + variableRateSlope2, + stableRateSlope1, + stableRateSlope2 + ] + }); + // TEST } // tx1 and tx2 gas is accounted for later. // Deploy stable and variable deployers and save implementations const tx1 = await waitForTx( - await stableAndVariableDeployer.initDeployment(tokens, symbols, incentivesController) + await stableAndVariableDeployer.initDeployment(tokens, symbols) ); tx1.events?.forEach((event, index) => { rawInsertContractAddressInDb(`stableDebt${symbols[index]}`, event?.args?.stableToken); @@ -144,13 +170,7 @@ export const initReservesByHelper = async ( // Deploy atokens and rate strategies and save implementations const tx2 = await waitForTx( - await atokenAndRatesDeployer.initDeployment( - tokens, - symbols, - strategyRates, - treasuryAddress, - incentivesController - ) + await atokenAndRatesDeployer.initDeployment(inputParams) ); tx2.events?.forEach((event, index) => { rawInsertContractAddressInDb(`a${symbols[index]}`, event?.args?.aToken); @@ -317,6 +337,16 @@ export const configureReservesByHelper = async ( const liquidationBonuses: string[] = []; const reserveFactors: string[] = []; const stableRatesEnabled: boolean[] = []; + // TEST + const inputParams : { + asset: string; + baseLTV: BigNumberish; + liquidationThreshold: BigNumberish; + liquidationBonus: BigNumberish; + reserveFactor: BigNumberish; + stableBorrowingEnabled: boolean; + }[] = []; + // TEST for (const [ assetSymbol, @@ -345,6 +375,18 @@ export const configureReservesByHelper = async ( continue; } // Push data + + // TEST + inputParams.push({ + asset: tokenAddress, + baseLTV: baseLTVAsCollateral, + liquidationThreshold: liquidationThreshold, + liquidationBonus: liquidationBonus, + reserveFactor: reserveFactor, + stableBorrowingEnabled: stableBorrowRateEnabled + }); + // TEST + tokens.push(tokenAddress); symbols.push(assetSymbol); baseLTVA.push(baseLTVAsCollateral); @@ -368,25 +410,28 @@ export const configureReservesByHelper = async ( const chunkedReserveFactors = chunk(reserveFactors, enableChunks); const chunkedStableRatesEnabled = chunk(stableRatesEnabled, enableChunks); + // TEST + const chunkedInputParams = chunk(inputParams, enableChunks); + // TEST + + console.log(`- Configure reserves in ${chunkedTokens.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedTokens.length; chunkIndex++) { - addGas(await atokenAndRatesDeployer.estimateGas.configureReserves( - chunkedTokens[chunkIndex], - chunkedBase[chunkIndex], - chunkedliquidationThresholds[chunkIndex], - chunkedliquidationBonuses[chunkIndex], - chunkedReserveFactors[chunkIndex], - chunkedStableRatesEnabled[chunkIndex], - { gasLimit: 12000000 } - )); + // addGas(await atokenAndRatesDeployer.estimateGas.configureReserves( + // chunkedTokens[chunkIndex], + // chunkedBase[chunkIndex], + // chunkedliquidationThresholds[chunkIndex], + // chunkedliquidationBonuses[chunkIndex], + // chunkedReserveFactors[chunkIndex], + // chunkedStableRatesEnabled[chunkIndex], + // { gasLimit: 12000000 } + // )); + + + await waitForTx( await atokenAndRatesDeployer.configureReserves( - chunkedTokens[chunkIndex], - chunkedBase[chunkIndex], - chunkedliquidationThresholds[chunkIndex], - chunkedliquidationBonuses[chunkIndex], - chunkedReserveFactors[chunkIndex], - chunkedStableRatesEnabled[chunkIndex], + chunkedInputParams[chunkIndex], { gasLimit: 12000000 } ) ); diff --git a/markets/uniswap/reservesConfigs.ts b/markets/uniswap/reservesConfigs.ts index acd09475..6961d4d5 100644 --- a/markets/uniswap/reservesConfigs.ts +++ b/markets/uniswap/reservesConfigs.ts @@ -77,7 +77,7 @@ export const strategyUSDT: IReserveParams = { variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(), stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(), stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(), - baseLTVAsCollateral: '8000', + baseLTVAsCollateral: '-1', liquidationThreshold: '8500', liquidationBonus: '10500', borrowingEnabled: true, From 34d764299003bfa3f14d15955203ae6291948f4a Mon Sep 17 00:00:00 2001 From: eboado Date: Sun, 31 Jan 2021 22:06:10 +0100 Subject: [PATCH 052/219] - Fixed incompatible initialize() interface on LendingPool --- contracts/protocol/lendingpool/LendingPool.sol | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 75e80230..0f4d9674 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -82,20 +82,12 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage * - Caching the address of the LendingPoolAddressesProvider in order to reduce gas consumption * on subsequent operations * @param provider The address of the LendingPoolAddressesProvider - * @param maxStableRateBorrowSizePercent The percentage of available liquidity that can be borrowed at once at stable rate - * @param flashLoanPremiumTotal The fee on flash loans - * @param maxNumberOfReserves Maximum number of reserves supported to be listed in this LendingPool **/ - function initialize( - ILendingPoolAddressesProvider provider, - uint256 maxStableRateBorrowSizePercent, - uint256 flashLoanPremiumTotal, - uint256 maxNumberOfReserves - ) public initializer { + function initialize(ILendingPoolAddressesProvider provider) public initializer { _addressesProvider = provider; - _maxStableRateBorrowSizePercent = maxStableRateBorrowSizePercent; - _flashLoanPremiumTotal = flashLoanPremiumTotal; - _maxNumberOfReserves = maxNumberOfReserves; + _maxStableRateBorrowSizePercent = 2500; + _flashLoanPremiumTotal = 9; + _maxNumberOfReserves = 128; } /** From 211dca7a07c7959067074c7c68b58734742a8c2b Mon Sep 17 00:00:00 2001 From: David Racero Date: Mon, 1 Feb 2021 13:24:07 +0100 Subject: [PATCH 053/219] Add new variable borrowedAssetLeftovers to improve readability --- contracts/adapters/FlashLiquidationAdapter.sol | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/contracts/adapters/FlashLiquidationAdapter.sol b/contracts/adapters/FlashLiquidationAdapter.sol index 1f329e0a..d488ee7b 100644 --- a/contracts/adapters/FlashLiquidationAdapter.sol +++ b/contracts/adapters/FlashLiquidationAdapter.sol @@ -37,6 +37,7 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { uint256 flashLoanDebt; uint256 soldAmount; uint256 remainingTokens; + uint256 borrowedAssetLeftovers; } constructor( @@ -104,7 +105,7 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { address user, uint256 debtToCover, bool useEthPath, - uint256 flashBorrowedAmount, // 1000 + uint256 flashBorrowedAmount, uint256 premium, address initiator ) internal { @@ -112,8 +113,11 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { vars.initCollateralBalance = IERC20(collateralAsset).balanceOf(address(this)); if (collateralAsset != borrowedAsset) { vars.initFlashBorrowedBalance = IERC20(borrowedAsset).balanceOf(address(this)); + + // Track leftover balance to rescue funds in case of external transfers into this contract + vars.borrowedAssetLeftovers = vars.initFlashBorrowedBalance.sub(flashBorrowedAmount); } - vars.flashLoanDebt = flashBorrowedAmount.add(premium); // 1010 + vars.flashLoanDebt = flashBorrowedAmount.add(premium); // Approve LendingPool to use debt token for liquidation IERC20(borrowedAsset).approve(address(LENDING_POOL), debtToCover); @@ -124,15 +128,16 @@ contract FlashLiquidationAdapter is BaseUniswapAdapter { // Discover the liquidated tokens uint256 collateralBalanceAfter = IERC20(collateralAsset).balanceOf(address(this)); + // Track only collateral released, not current asset balance of the contract vars.diffCollateralBalance = collateralBalanceAfter.sub(vars.initCollateralBalance); if (collateralAsset != borrowedAsset) { - // Discover flash loan balance + // Discover flash loan balance after the liquidation uint256 flashBorrowedAssetAfter = IERC20(borrowedAsset).balanceOf(address(this)); - vars.diffFlashBorrowedBalance = flashBorrowedAssetAfter.sub( - vars.initFlashBorrowedBalance.sub(flashBorrowedAmount) - ); + // Use only flash loan borrowed assets, not current asset balance of the contract + vars.diffFlashBorrowedBalance = flashBorrowedAssetAfter.sub(vars.borrowedAssetLeftovers); + // Swap released collateral into the debt asset, to repay the flash loan vars.soldAmount = _swapTokensForExactTokens( collateralAsset, From 00f414b681d7e0b8f0714ee843d2c75eb79b8097 Mon Sep 17 00:00:00 2001 From: emilio Date: Mon, 1 Feb 2021 16:16:42 +0100 Subject: [PATCH 054/219] Updated test description --- test/helpers/scenarios/rebalance-stable-rate.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/helpers/scenarios/rebalance-stable-rate.json b/test/helpers/scenarios/rebalance-stable-rate.json index 8c7e6c19..1da9a376 100644 --- a/test/helpers/scenarios/rebalance-stable-rate.json +++ b/test/helpers/scenarios/rebalance-stable-rate.json @@ -19,7 +19,7 @@ ] }, { - "description": "User 0 deposits 1000 USDC, user 1 deposits 5 ETH, borrows 600 DAI at a variable rate, user 0 rebalances user 1 (revert expected)", + "description": "User 0 deposits 1000 USDC, user 1 deposits 5 ETH, borrows 250 USDC at a stable rate, user 0 rebalances user 1 (revert expected)", "actions": [ { "name": "mint", From a4a6d3d4374d53e9fd312f173d393667540d2b39 Mon Sep 17 00:00:00 2001 From: David Racero Date: Mon, 1 Feb 2021 16:40:11 +0100 Subject: [PATCH 055/219] WIP change implementation of increaseTime --- helpers/misc-utils.ts | 20 ++++++++++++++++++++ test/helpers/actions.ts | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/helpers/misc-utils.ts b/helpers/misc-utils.ts index 56be2cdf..54d5fa44 100644 --- a/helpers/misc-utils.ts +++ b/helpers/misc-utils.ts @@ -46,6 +46,26 @@ export const increaseTime = async (secondsToIncrease: number) => { await DRE.ethers.provider.send('evm_mine', []); }; +// Workaround for time travel tests bug: https://github.com/Tonyhaenn/hh-time-travel/blob/0161d993065a0b7585ec5a043af2eb4b654498b8/test/test.js#L12 +export const advanceTimeAndBlock = async function (forwardTime: number) { + const currentBlockNumber = await DRE.ethers.provider.getBlockNumber(); + const currentBlock = await DRE.ethers.provider.getBlock(currentBlockNumber); + + if (currentBlock === null) { + /* Workaround for https://github.com/nomiclabs/hardhat/issues/1183 + */ + await DRE.ethers.provider.send('evm_increaseTime', [forwardTime]); + await DRE.ethers.provider.send('evm_mine', []); + //Set the next blocktime back to 15 seconds + await DRE.ethers.provider.send('evm_increaseTime', [15]); + return; + } + const currentTime = currentBlock.timestamp; + const futureTime = currentTime + forwardTime; + await DRE.ethers.provider.send('evm_setNextBlockTimestamp', [futureTime]); + await DRE.ethers.provider.send('evm_mine', []); +}; + export const waitForTx = async (tx: ContractTransaction) => await tx.wait(1); export const filterMapBy = (raw: { [key: string]: any }, fn: (key: string) => boolean) => diff --git a/test/helpers/actions.ts b/test/helpers/actions.ts index cbe06e5c..c41c92e5 100644 --- a/test/helpers/actions.ts +++ b/test/helpers/actions.ts @@ -26,7 +26,7 @@ import { } from '../../helpers/contracts-getters'; import { MAX_UINT_AMOUNT, ONE_YEAR } from '../../helpers/constants'; import { SignerWithAddress, TestEnv } from './make-suite'; -import { DRE, increaseTime, timeLatest, waitForTx } from '../../helpers/misc-utils'; +import { advanceTimeAndBlock, DRE, timeLatest, waitForTx } from '../../helpers/misc-utils'; import chai from 'chai'; import { ReserveData, UserReserveData } from './utils/interfaces'; @@ -361,7 +361,7 @@ export const borrow = async ( if (timeTravel) { const secondsToTravel = new BigNumber(timeTravel).multipliedBy(ONE_YEAR).div(365).toNumber(); - await increaseTime(secondsToTravel); + await advanceTimeAndBlock(secondsToTravel); } const { From 3f6dd8a0f040b50368d188ce69db9c8642d10297 Mon Sep 17 00:00:00 2001 From: David Racero Date: Mon, 1 Feb 2021 17:54:02 +0100 Subject: [PATCH 056/219] Update hardhat to latest version. Add timeout to advanceTimeAndBlock function. --- helpers/misc-utils.ts | 3 +++ package-lock.json | 14 +++++++------- package.json | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/helpers/misc-utils.ts b/helpers/misc-utils.ts index 54d5fa44..fd26ad68 100644 --- a/helpers/misc-utils.ts +++ b/helpers/misc-utils.ts @@ -62,8 +62,11 @@ export const advanceTimeAndBlock = async function (forwardTime: number) { } const currentTime = currentBlock.timestamp; const futureTime = currentTime + forwardTime; + await new Promise((r) => setTimeout(r, 500)); await DRE.ethers.provider.send('evm_setNextBlockTimestamp', [futureTime]); + await new Promise((r) => setTimeout(r, 500)); await DRE.ethers.provider.send('evm_mine', []); + await new Promise((r) => setTimeout(r, 500)); }; export const waitForTx = async (tx: ContractTransaction) => await tx.wait(1); diff --git a/package-lock.json b/package-lock.json index 3ae83800..7df01b18 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15287,14 +15287,14 @@ } }, "hardhat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.0.3.tgz", - "integrity": "sha512-mDygAl+1qd5KBdXQBfc3R5XmC/rVdYYbEuOTSQY3rlncVu9gfockZVDsHtAMPw/FiBIRMApLcOceK7D1XQmHRw==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.0.8.tgz", + "integrity": "sha512-2tDAtOfshrBzP103dx7PQrhTwv2sqjhQStZAPwkkQTic25o2EH6HYE2++LuOG98YwqSjr0WvhvdBvKl3dCSkYA==", "dev": true, "requires": { "@nomiclabs/ethereumjs-vm": "^4.1.1", "@sentry/node": "^5.18.1", - "@solidity-parser/parser": "^0.7.1", + "@solidity-parser/parser": "^0.11.0", "@types/bn.js": "^4.11.5", "@types/lru-cache": "^5.1.0", "abort-controller": "^3.0.0", @@ -15339,9 +15339,9 @@ }, "dependencies": { "@solidity-parser/parser": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.7.1.tgz", - "integrity": "sha512-5ma2uuwPAEX1TPl2rAPAAuGlBkKnn2oUKQvnhTFlDIB8U/KDWX77FpHtL6Rcz+OwqSCWx9IClxACgyIEJ/GhIw==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.11.1.tgz", + "integrity": "sha512-H8BSBoKE8EubJa0ONqecA2TviT3TnHeC4NpgnAHSUiuhZoQBfPB4L2P9bs8R6AoTW10Endvh3vc+fomVMIDIYQ==", "dev": true }, "commander": { diff --git a/package.json b/package.json index d8db5d38..1f8d3043 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "ethereumjs-util": "7.0.2", "ethers": "^5.0.19", "globby": "^11.0.1", - "hardhat": "^2.0.2", + "hardhat": "^2.0.8", "hardhat-gas-reporter": "^1.0.0", "hardhat-typechain": "^0.3.3", "husky": "^4.2.5", From f106502c72b0dd732eea6d726699ca83619d6386 Mon Sep 17 00:00:00 2001 From: David Racero Date: Mon, 1 Feb 2021 19:24:50 +0100 Subject: [PATCH 057/219] Add retries to scenarios to prevent random networking bug. --- helpers/misc-utils.ts | 3 --- test/scenario.spec.ts | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/helpers/misc-utils.ts b/helpers/misc-utils.ts index fd26ad68..54d5fa44 100644 --- a/helpers/misc-utils.ts +++ b/helpers/misc-utils.ts @@ -62,11 +62,8 @@ export const advanceTimeAndBlock = async function (forwardTime: number) { } const currentTime = currentBlock.timestamp; const futureTime = currentTime + forwardTime; - await new Promise((r) => setTimeout(r, 500)); await DRE.ethers.provider.send('evm_setNextBlockTimestamp', [futureTime]); - await new Promise((r) => setTimeout(r, 500)); await DRE.ethers.provider.send('evm_mine', []); - await new Promise((r) => setTimeout(r, 500)); }; export const waitForTx = async (tx: ContractTransaction) => await tx.wait(1); diff --git a/test/scenario.spec.ts b/test/scenario.spec.ts index 13037cfb..6ddf43d4 100644 --- a/test/scenario.spec.ts +++ b/test/scenario.spec.ts @@ -34,7 +34,8 @@ fs.readdirSync(scenarioFolder).forEach((file) => { }); for (const story of scenario.stories) { - it(story.description, async () => { + it(story.description, async function () { + this.retries(4); await executeStory(story, testEnv); }); } From 57996bd5b876547272e781cbfd8612ea0989ef04 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 1 Feb 2021 16:10:14 -0500 Subject: [PATCH 058/219] Pulled lendingPool fix from origin --- contracts/protocol/lendingpool/LendingPool.sol | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 75e80230..0f4d9674 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -82,20 +82,12 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage * - Caching the address of the LendingPoolAddressesProvider in order to reduce gas consumption * on subsequent operations * @param provider The address of the LendingPoolAddressesProvider - * @param maxStableRateBorrowSizePercent The percentage of available liquidity that can be borrowed at once at stable rate - * @param flashLoanPremiumTotal The fee on flash loans - * @param maxNumberOfReserves Maximum number of reserves supported to be listed in this LendingPool **/ - function initialize( - ILendingPoolAddressesProvider provider, - uint256 maxStableRateBorrowSizePercent, - uint256 flashLoanPremiumTotal, - uint256 maxNumberOfReserves - ) public initializer { + function initialize(ILendingPoolAddressesProvider provider) public initializer { _addressesProvider = provider; - _maxStableRateBorrowSizePercent = maxStableRateBorrowSizePercent; - _flashLoanPremiumTotal = flashLoanPremiumTotal; - _maxNumberOfReserves = maxNumberOfReserves; + _maxStableRateBorrowSizePercent = 2500; + _flashLoanPremiumTotal = 9; + _maxNumberOfReserves = 128; } /** From 221c19c910179a60c0c37914323098efac71feeb Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 1 Feb 2021 18:23:11 -0500 Subject: [PATCH 059/219] Tentative fix in init-helpers for light deployment --- helpers/init-helpers.ts | 92 +++++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 18 deletions(-) diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index a8794df2..8b5a8388 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -12,6 +12,7 @@ import { getAToken, getATokensAndRatesHelper, getLendingPoolAddressesProvider, + getLendingPoolConfiguratorProxy, getStableAndVariableTokensHelper, } from './contracts-getters'; import { rawInsertContractAddressInDb } from './contracts-helpers'; @@ -26,6 +27,7 @@ import { import { ZERO_ADDRESS } from './constants'; import { isZeroAddress } from 'ethereumjs-util'; import { addGas } from '../gas-tracker'; +import { getTreasuryAddress } from './configuration'; const chooseATokenDeployment = (id: eContractid) => { switch (id) { @@ -77,11 +79,32 @@ export const initReservesByHelper = async ( let reserveInitDecimals: string[] = []; let reserveSymbols: string[] = []; + // TEST START + let initInputParams: { + aTokenImpl: string, + stableDebtTokenImpl: string, + variableDebtTokenImpl: string, + underlyingAssetDecimals: BigNumberish, + interestRateStrategyAddress: string, + underlyingAsset: string, + treasury: string, + incentivesController: string, + underlyingAssetName: string, + aTokenName: string, + aTokenSymbol: string, + variableDebtTokenName: string, + variableDebtTokenSymbol: string, + stableDebtTokenName: string, + stableDebtTokenSymbol: string, + }[] = []; + // TEST END + 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[] = []; @@ -95,7 +118,7 @@ export const initReservesByHelper = async ( BigNumberish ][] = []; const reservesDecimals: string[] = []; - // TEST + // TEST START const inputParams: { asset: string, rates: [ @@ -107,7 +130,7 @@ export const initReservesByHelper = async ( BigNumberish ] }[] = []; - // TEST + // TEST END for (let [assetSymbol, { reserveDecimals }] of reservesChunk) { const assetAddressIndex = Object.keys(tokenAddresses).findIndex( (value) => value === assetSymbol @@ -143,7 +166,7 @@ export const initReservesByHelper = async ( ]); reservesDecimals.push(reserveDecimals); - // TEST + // TEST START inputParams.push({ asset: tokenAddress, rates: [ @@ -155,7 +178,7 @@ export const initReservesByHelper = async ( stableRateSlope2 ] }); - // TEST + // TEST END } // tx1 and tx2 gas is accounted for later. @@ -181,7 +204,7 @@ export const initReservesByHelper = async ( console.log(' * gasUsed: debtTokens batch', tx1.gasUsed.toString()); console.log(' * gasUsed: aTokens and Strategy batch', tx2.gasUsed.toString()); gasUsage = gasUsage.add(tx1.gasUsed).add(tx2.gasUsed); - addGas(gasUsage); + 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) || []; @@ -196,6 +219,29 @@ export const initReservesByHelper = async ( reserveSymbols = [...reserveSymbols, ...symbols]; } + // TEST START + for (let i = 0; i < deployedATokens.length; i ++) { + initInputParams.push({ + aTokenImpl: deployedATokens[i], + stableDebtTokenImpl: deployedStableTokens[i], + variableDebtTokenImpl: deployedVariableTokens[i], + underlyingAssetDecimals: reserveInitDecimals[i], + interestRateStrategyAddress: deployedRates[i], + underlyingAsset: reserveTokens[i], + treasury: treasuryAddress, + incentivesController: ZERO_ADDRESS, + underlyingAssetName: reserveSymbols[i], + aTokenName: `Aave Interest Bearing ${reserveSymbols[i]}`, + aTokenSymbol: `a${reserveSymbols[i]}`, + variableDebtTokenName: `Aave Variable Debt ${reserveSymbols[i]}`, + variableDebtTokenSymbol: `variableDebt${reserveSymbols[i]}`, + stableDebtTokenName: `Aave Stable Debt ${reserveSymbols[i]}`, + stableDebtTokenSymbol: `stableDebt${reserveSymbols[i]}` + }); + } + // TEST END + + // Deploy delegated aware reserves tokens const delegatedAwareReserves = Object.entries(reservesParams).filter( ([_, { aTokenImpl }]) => aTokenImpl === eContractid.DelegationAwareAToken @@ -273,24 +319,34 @@ export const initReservesByHelper = async ( const chunkedDecimals = chunk(reserveInitDecimals, initChunks); const chunkedSymbols = chunk(reserveSymbols, initChunks); + // TEST START + const configurator = await getLendingPoolConfiguratorProxy(); + await waitForTx(await addressProvider.setPoolAdmin(admin)); + + const chunkedInitInputParams = chunk(initInputParams, initChunks); + // TEST END console.log(`- Reserves initialization in ${chunkedStableTokens.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedDecimals.length; chunkIndex++) { const tx3 = await waitForTx( - await atokenAndRatesDeployer.initReserve( - chunkedStableTokens[chunkIndex], - chunkedVariableTokens[chunkIndex], - chunkedAtokens[chunkIndex], - chunkedRates[chunkIndex], - chunkedDecimals[chunkIndex] - ) + // await atokenAndRatesDeployer.initReserve( + // chunkedStableTokens[chunkIndex], + // chunkedVariableTokens[chunkIndex], + // chunkedAtokens[chunkIndex], + // chunkedRates[chunkIndex], + // chunkedDecimals[chunkIndex] + // ) + await configurator.batchInitReserve(chunkedInitInputParams[chunkIndex]) + ); console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`); console.log(' * gasUsed', tx3.gasUsed.toString()); gasUsage = gasUsage.add(tx3.gasUsed); } + addGas(gasUsage); // Set deployer back as admin + addGas(await addressProvider.estimateGas.setPoolAdmin(admin)); await waitForTx(await addressProvider.setPoolAdmin(admin)); return gasUsage; }; @@ -337,7 +393,7 @@ export const configureReservesByHelper = async ( const liquidationBonuses: string[] = []; const reserveFactors: string[] = []; const stableRatesEnabled: boolean[] = []; - // TEST + // TEST START const inputParams : { asset: string; baseLTV: BigNumberish; @@ -346,7 +402,7 @@ export const configureReservesByHelper = async ( reserveFactor: BigNumberish; stableBorrowingEnabled: boolean; }[] = []; - // TEST + // TEST END for (const [ assetSymbol, @@ -376,7 +432,7 @@ export const configureReservesByHelper = async ( } // Push data - // TEST + // TEST START inputParams.push({ asset: tokenAddress, baseLTV: baseLTVAsCollateral, @@ -385,7 +441,7 @@ export const configureReservesByHelper = async ( reserveFactor: reserveFactor, stableBorrowingEnabled: stableBorrowRateEnabled }); - // TEST + // TEST END tokens.push(tokenAddress); symbols.push(assetSymbol); @@ -410,9 +466,9 @@ export const configureReservesByHelper = async ( const chunkedReserveFactors = chunk(reserveFactors, enableChunks); const chunkedStableRatesEnabled = chunk(stableRatesEnabled, enableChunks); - // TEST + // TEST START const chunkedInputParams = chunk(inputParams, enableChunks); - // TEST + // TEST END console.log(`- Configure reserves in ${chunkedTokens.length} txs`); From d63ae5405f7a3b50c6d525aaf3833aa2a327d1bb Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 1 Feb 2021 18:42:01 -0500 Subject: [PATCH 060/219] Fixed missing gas estimation --- helpers/init-helpers.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 8b5a8388..58748d67 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -484,6 +484,10 @@ export const configureReservesByHelper = async ( // )); + addGas(await atokenAndRatesDeployer.estimateGas.configureReserves( + chunkedInputParams[chunkIndex], + { gasLimit: 12000000 } + )); await waitForTx( await atokenAndRatesDeployer.configureReserves( From ca0e744df51f97313768c43abe396ad514b578c6 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 1 Feb 2021 22:12:36 -0500 Subject: [PATCH 061/219] Fixed delegation aware aToken test --- test/delegation-aware-atoken.spec.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/delegation-aware-atoken.spec.ts b/test/delegation-aware-atoken.spec.ts index 0e782495..903979e6 100644 --- a/test/delegation-aware-atoken.spec.ts +++ b/test/delegation-aware-atoken.spec.ts @@ -33,9 +33,13 @@ makeSuite('AToken: underlying delegation', (testEnv: TestEnv) => { delegationERC20 = await deployMintableDelegationERC20(['DEL', 'DEL', '18']); delegationAToken = await deployDelegationAwareAToken( - [pool.address, delegationERC20.address, ZERO_ADDRESS, 'aDEL', 'aDEL', ZERO_ADDRESS], + [pool.address, ZERO_ADDRESS, delegationERC20.address, ZERO_ADDRESS, '18', 'aDEL', 'aDEL'], false ); + + await delegationAToken.initialize(pool.address, ZERO_ADDRESS, delegationERC20.address, ZERO_ADDRESS, '18', 'aDEL', 'aDEL'); + + console.log((await delegationAToken.decimals()).toString()); }); it('Tries to delegate with the caller not being the Aave admin', async () => { From 19436c055ee113cf72368c9677218cb5cd88bfbf Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Tue, 2 Feb 2021 16:38:34 -0500 Subject: [PATCH 062/219] Pulled waitForTx changes --- test/helpers/actions.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/helpers/actions.ts b/test/helpers/actions.ts index b33f146d..cbe06e5c 100644 --- a/test/helpers/actions.ts +++ b/test/helpers/actions.ts @@ -128,7 +128,9 @@ export const approve = async (reserveSymbol: string, user: SignerWithAddress, te const token = await getMintableERC20(reserve); - await token.connect(user.signer).approve(pool.address, '100000000000000000000000000000'); + await waitForTx( + await token.connect(user.signer).approve(pool.address, '100000000000000000000000000000') + ); }; export const deposit = async ( @@ -314,7 +316,7 @@ export const delegateBorrowAllowance = async ( await expect(delegateAllowancePromise, revertMessage).to.be.revertedWith(revertMessage); return; } else { - await delegateAllowancePromise; + await waitForTx(await delegateAllowancePromise); const allowance = await debtToken.borrowAllowance(user.address, receiver); expect(allowance.toString()).to.be.equal( amountToDelegate, From 9431541593a6f1a002e92ca4d12588268d230201 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Tue, 2 Feb 2021 17:44:46 -0500 Subject: [PATCH 063/219] More fixes, some stable tests fail WIP --- .../protocol/lendingpool/LendingPool.sol | 5 +- .../libraries/logic/ValidationLogic.sol | 4 +- helpers/contracts-deployments.ts | 164 +++++++++++++----- helpers/init-helpers.ts | 26 +-- test/delegation-aware-atoken.spec.ts | 6 +- test/helpers/actions.ts | 5 +- test/upgradeability.spec.ts | 126 ++++++++++++-- 7 files changed, 260 insertions(+), 76 deletions(-) diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 0f4d9674..7164227d 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -26,6 +26,9 @@ import {UserConfiguration} from '../libraries/configuration/UserConfiguration.so import {DataTypes} from '../libraries/types/DataTypes.sol'; import {LendingPoolStorage} from './LendingPoolStorage.sol'; +// TEST +import { console } from 'hardhat/console.sol'; + /** * @title LendingPool contract * @dev Main point of interaction with an Aave protocol's market @@ -206,7 +209,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage address onBehalfOf ) external override whenNotPaused { DataTypes.ReserveData storage reserve = _reserves[asset]; - + _executeBorrow( ExecuteBorrowParams( asset, diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index 080b792d..89d7c323 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -16,6 +16,8 @@ import {Helpers} from '../helpers/Helpers.sol'; import {IReserveInterestRateStrategy} from '../../../interfaces/IReserveInterestRateStrategy.sol'; import {DataTypes} from '../types/DataTypes.sol'; +import {console} from 'hardhat/console.sol'; + /** * @title ReserveLogic library * @author Aave @@ -194,7 +196,7 @@ library ValidationLogic { //check if the borrow mode is stable and if stable rate borrowing is enabled on this reserve require(vars.stableRateBorrowingEnabled, Errors.VL_STABLE_BORROWING_NOT_ENABLED); - + console.log("Reserve aToken balance on borrowing address:", IERC20(reserve.aTokenAddress).balanceOf(userAddress)); require( !userConfig.isUsingAsCollateral(reserve.id) || reserve.configuration.getLtv() == 0 || diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 1e5940eb..ee7ef103 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -298,79 +298,111 @@ export const deployDefaultReserveInterestRateStrategy = async ( export const deployStableDebtToken = async ( args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], verify: boolean -) => - withSaveAndVerify( +) => { + const instance = await withSaveAndVerify( await new StableDebtTokenFactory(await getFirstSigner()).deploy(), eContractid.StableDebtToken, - args, + [], verify ); + await instance.initialize( + args[0], + args[1], + args[2], + "18", + args[3], + args[4] + ); + + return instance; +} + + export const deployVariableDebtToken = async ( args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], verify: boolean -) => - withSaveAndVerify( +) => { + const instance = await withSaveAndVerify( await new VariableDebtTokenFactory(await getFirstSigner()).deploy(), eContractid.VariableDebtToken, - args, + [], verify ); + await instance.initialize( + args[0], + args[1], + args[2], + "18", + args[3], + args[4] + ); + + return instance; +} + + export const deployGenericAToken = async ( - [poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol,incentivesController]: [ + [poolAddress, underlyingAssetAddress, treasuryAddress, incentivesController, name, symbol]: [ + tEthereumAddress, tEthereumAddress, tEthereumAddress, tEthereumAddress, string, - string, - tEthereumAddress + string ], verify: boolean ) => { - const args: [ - tEthereumAddress, - tEthereumAddress, - string, - string, - tEthereumAddress, - tEthereumAddress - - ] = [poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController]; - return withSaveAndVerify( + const instance = await withSaveAndVerify( await new ATokenFactory(await getFirstSigner()).deploy(), eContractid.AToken, - args, + [], verify ); + + await instance.initialize( + poolAddress, + treasuryAddress, + underlyingAssetAddress, + incentivesController, + "18", + name, + symbol + ); + + return instance; }; export const deployDelegationAwareAToken = async ( - [poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController]: [ + [pool, underlyingAssetAddress, treasuryAddress, incentivesController, name, symbol]: [ + tEthereumAddress, tEthereumAddress, tEthereumAddress, tEthereumAddress, string, - string, - tEthereumAddress + string ], verify: boolean ) => { - const args: [ - tEthereumAddress, - tEthereumAddress, - string, - string, - tEthereumAddress, - tEthereumAddress - ] = [poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController]; - - return withSaveAndVerify( + const instance = await withSaveAndVerify( await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(), eContractid.DelegationAwareAToken, - args, + [], verify ); + + await instance.initialize( + pool, + treasuryAddress, + underlyingAssetAddress, + incentivesController, + "18", + name, + symbol + ) + + return instance; }; export const deployAllMockTokens = async (verify?: boolean) => { @@ -447,16 +479,29 @@ export const deployWETHGateway = async ( ); export const deployMockStableDebtToken = async ( - args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], + args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], verify?: boolean -) => - withSaveAndVerify( +) => { + const instance = await withSaveAndVerify( await new MockStableDebtTokenFactory(await getFirstSigner()).deploy(), eContractid.MockStableDebtToken, - args, + [], verify ); + await instance.initialize( + args[0], + args[1], + args[2], + "18", + args[3], + args[4] + ); + + return instance; +} + + export const deployWETHMocked = async (verify?: boolean) => withSaveAndVerify( await new WETH9MockedFactory(await getFirstSigner()).deploy(), @@ -466,26 +511,53 @@ export const deployWETHMocked = async (verify?: boolean) => ); export const deployMockVariableDebtToken = async ( - args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], + args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], verify?: boolean -) => - withSaveAndVerify( +) => { + const instance = await withSaveAndVerify( await new MockVariableDebtTokenFactory(await getFirstSigner()).deploy(), eContractid.MockVariableDebtToken, - args, + [], verify ); + await instance.initialize( + args[0], + args[1], + args[2], + "18", + args[3], + args[4] + ); + + return instance; +} + + export const deployMockAToken = async ( - args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], +args: [tEthereumAddress, tEthereumAddress, tEthereumAddress,tEthereumAddress, string, string], verify?: boolean -) => - withSaveAndVerify( +) => { + const instance = await withSaveAndVerify( await new MockATokenFactory(await getFirstSigner()).deploy(), eContractid.MockAToken, - args, + [], verify ); + + await instance.initialize( + args[0], + args[2], + args[1], + args[3], + "18", + args[4], + args[5], + ); + + return instance; +} + export const deploySelfdestructTransferMock = async (verify?: boolean) => withSaveAndVerify( diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 58748d67..623483e5 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -231,11 +231,11 @@ export const initReservesByHelper = async ( treasury: treasuryAddress, incentivesController: ZERO_ADDRESS, underlyingAssetName: reserveSymbols[i], - aTokenName: `Aave Interest Bearing ${reserveSymbols[i]}`, + aTokenName: `Aave interest bearing ${reserveSymbols[i]}`, aTokenSymbol: `a${reserveSymbols[i]}`, - variableDebtTokenName: `Aave Variable Debt ${reserveSymbols[i]}`, + variableDebtTokenName: `Aave variable debt bearing ${reserveSymbols[i]}`, variableDebtTokenSymbol: `variableDebt${reserveSymbols[i]}`, - stableDebtTokenName: `Aave Stable Debt ${reserveSymbols[i]}`, + stableDebtTokenName: `Aave stable debt bearing ${reserveSymbols[i]}`, stableDebtTokenSymbol: `stableDebt${reserveSymbols[i]}` }); } @@ -263,9 +263,9 @@ export const initReservesByHelper = async ( poolAddress, tokenAddresses[symbol], treasuryAddress, + ZERO_ADDRESS, `Aave interest bearing ${symbol}`, `a${symbol}`, - ZERO_ADDRESS, ], verify ); @@ -273,9 +273,9 @@ export const initReservesByHelper = async ( [ poolAddress, tokenAddresses[symbol], + ZERO_ADDRESS, // Incentives controller `Aave stable debt bearing ${symbol}`, - `stableDebt${symbol}`, - ZERO_ADDRESS, + `stableDebt${symbol}` ], verify ); @@ -283,9 +283,9 @@ export const initReservesByHelper = async ( [ poolAddress, tokenAddresses[symbol], + ZERO_ADDRESS, // Incentives controller `Aave variable debt bearing ${symbol}`, `variableDebt${symbol}`, - ZERO_ADDRESS, ], verify ); @@ -573,9 +573,9 @@ export const initTokenReservesByHelper = async ( [ poolAddress, tokenAddresses[symbol], + ZERO_ADDRESS, // Incentives controller `Aave stable debt bearing ${symbol}`, - `stableDebt${symbol}`, - ZERO_ADDRESS, + `stableDebt${symbol}` ], verify ); @@ -586,9 +586,9 @@ export const initTokenReservesByHelper = async ( [ poolAddress, tokenAddresses[symbol], + ZERO_ADDRESS, // Incentives Controller `Aave variable debt bearing ${symbol}`, - `variableDebt${symbol}`, - ZERO_ADDRESS, + `variableDebt${symbol}` ], verify ); @@ -604,9 +604,9 @@ export const initTokenReservesByHelper = async ( poolAddress, tokenAddresses[symbol], treasuryAddress, - `Aave interest bearing ${symbol}`, - `a${symbol}`, ZERO_ADDRESS, + `Aave interest bearing ${symbol}`, + `a${symbol}` ], verify ); diff --git a/test/delegation-aware-atoken.spec.ts b/test/delegation-aware-atoken.spec.ts index 903979e6..7b04913e 100644 --- a/test/delegation-aware-atoken.spec.ts +++ b/test/delegation-aware-atoken.spec.ts @@ -9,6 +9,7 @@ import { DRE } from '../helpers/misc-utils'; import { ConfigNames, getATokenDomainSeparatorPerNetwork, + getTreasuryAddress, loadPoolConfig, } from '../helpers/configuration'; import { waitForTx } from '../helpers/misc-utils'; @@ -19,6 +20,7 @@ import { import { DelegationAwareATokenFactory } from '../types'; import { DelegationAwareAToken } from '../types/DelegationAwareAToken'; import { MintableDelegationERC20 } from '../types/MintableDelegationERC20'; +import AaveConfig from '../markets/aave'; const { parseEther } = ethers.utils; @@ -33,11 +35,11 @@ makeSuite('AToken: underlying delegation', (testEnv: TestEnv) => { delegationERC20 = await deployMintableDelegationERC20(['DEL', 'DEL', '18']); delegationAToken = await deployDelegationAwareAToken( - [pool.address, ZERO_ADDRESS, delegationERC20.address, ZERO_ADDRESS, '18', 'aDEL', 'aDEL'], + [pool.address, delegationERC20.address, await getTreasuryAddress(AaveConfig), ZERO_ADDRESS, 'aDEL', 'aDEL'], false ); - await delegationAToken.initialize(pool.address, ZERO_ADDRESS, delegationERC20.address, ZERO_ADDRESS, '18', 'aDEL', 'aDEL'); + //await delegationAToken.initialize(pool.address, ZERO_ADDRESS, delegationERC20.address, ZERO_ADDRESS, '18', 'aDEL', 'aDEL'); console.log((await delegationAToken.decimals()).toString()); }); diff --git a/test/helpers/actions.ts b/test/helpers/actions.ts index cbe06e5c..b1fa48a6 100644 --- a/test/helpers/actions.ts +++ b/test/helpers/actions.ts @@ -161,6 +161,9 @@ export const deposit = async ( if (sendValue) { txOptions.value = await convertToCurrencyDecimals(reserve, sendValue); } + + //console.log("Depositing %s %s, expecting %s", amountToDeposit.toString(), reserveSymbol, expectedResult); + if (expectedResult === 'success') { const txResult = await waitForTx( await pool @@ -348,7 +351,7 @@ export const borrow = async ( ); const amountToBorrow = await convertToCurrencyDecimals(reserve, amount); - + //console.log("Borrowing %s %s with rate mode %s expecting", amountToBorrow.toString(), reserveSymbol, interestRateMode, expectedResult); if (expectedResult === 'success') { const txResult = await waitForTx( await pool diff --git a/test/upgradeability.spec.ts b/test/upgradeability.spec.ts index 92ab1ee1..a7d62d37 100644 --- a/test/upgradeability.spec.ts +++ b/test/upgradeability.spec.ts @@ -10,6 +10,7 @@ import { getAToken, getMockStableDebtToken, getMockVariableDebtToken, + getStableDebtToken, getVariableDebtToken, } from '../helpers/contracts-getters'; import { @@ -30,25 +31,25 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { pool.address, dai.address, ZERO_ADDRESS, + ZERO_ADDRESS, 'Aave Interest bearing DAI updated', 'aDAI', - ZERO_ADDRESS, ]); const stableDebtTokenInstance = await deployMockStableDebtToken([ pool.address, dai.address, + ZERO_ADDRESS, 'Aave stable debt bearing DAI updated', 'stableDebtDAI', - ZERO_ADDRESS, ]); const variableDebtTokenInstance = await deployMockVariableDebtToken([ pool.address, dai.address, + ZERO_ADDRESS, 'Aave variable debt bearing DAI updated', 'variableDebtDAI', - ZERO_ADDRESS, ]); newATokenAddress = aTokenInstance.address; @@ -59,8 +60,26 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { it('Tries to update the DAI Atoken implementation with a different address than the lendingPoolManager', async () => { const {dai, configurator, users} = testEnv; + const name = await (await getAToken(newATokenAddress)).name(); + const symbol = await (await getAToken(newATokenAddress)).symbol(); + + const updateATokenInputParams: { + asset: string; + treasury: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + treasury: ZERO_ADDRESS, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newATokenAddress, + }; await expect( - configurator.connect(users[1].signer).updateAToken(dai.address, newATokenAddress) + configurator.connect(users[1].signer).updateAToken(updateATokenInputParams) ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); @@ -68,8 +87,24 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { const {dai, configurator, aDai} = testEnv; const name = await (await getAToken(newATokenAddress)).name(); + const symbol = await (await getAToken(newATokenAddress)).symbol(); - await configurator.updateAToken(dai.address, newATokenAddress); + const updateATokenInputParams: { + asset: string; + treasury: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + treasury: ZERO_ADDRESS, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newATokenAddress, + }; + await configurator.updateAToken(updateATokenInputParams); const tokenName = await aDai.name(); @@ -79,19 +114,53 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { it('Tries to update the DAI Stable debt token implementation with a different address than the lendingPoolManager', async () => { const {dai, configurator, users} = testEnv; + const name = await (await getStableDebtToken(newStableTokenAddress)).name(); + const symbol = await (await getStableDebtToken(newStableTokenAddress)).symbol(); + + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newStableTokenAddress, + } + await expect( configurator .connect(users[1].signer) - .updateStableDebtToken(dai.address, newStableTokenAddress) + .updateStableDebtToken(updateDebtTokenInput) ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); it('Upgrades the DAI stable debt token implementation ', async () => { const {dai, configurator, pool, helpersContract} = testEnv; - const name = await (await getAToken(newATokenAddress)).name(); + const name = await (await getStableDebtToken(newStableTokenAddress)).name(); + const symbol = await (await getStableDebtToken(newStableTokenAddress)).symbol(); - await configurator.updateStableDebtToken(dai.address, newStableTokenAddress); + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newStableTokenAddress, + } + + await configurator.updateStableDebtToken(updateDebtTokenInput); const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(dai.address); @@ -104,20 +173,53 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { it('Tries to update the DAI variable debt token implementation with a different address than the lendingPoolManager', async () => { const {dai, configurator, users} = testEnv; + + const name = await (await getVariableDebtToken(newVariableTokenAddress)).name(); + const symbol = await (await getVariableDebtToken(newVariableTokenAddress)).symbol(); + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newVariableTokenAddress, + } await expect( configurator .connect(users[1].signer) - .updateVariableDebtToken(dai.address, newVariableTokenAddress) + .updateVariableDebtToken(updateDebtTokenInput) ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); it('Upgrades the DAI variable debt token implementation ', async () => { const {dai, configurator, pool, helpersContract} = testEnv; + + const name = await (await getVariableDebtToken(newVariableTokenAddress)).name(); + const symbol = await (await getVariableDebtToken(newVariableTokenAddress)).symbol(); + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newVariableTokenAddress, + } + //const name = await (await getAToken(newATokenAddress)).name(); - const name = await (await getAToken(newATokenAddress)).name(); - - await configurator.updateVariableDebtToken(dai.address, newVariableTokenAddress); + await configurator.updateVariableDebtToken(updateDebtTokenInput); const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(dai.address); From 56e5efd47b36d639fbe3eecf44e2b2d95e354c6e Mon Sep 17 00:00:00 2001 From: David Racero <4266635-kartojal@users.noreply.gitlab.com> Date: Wed, 3 Feb 2021 09:22:22 +0000 Subject: [PATCH 064/219] Add a comment to specify why retries are being used at scenarios tests suite --- test/scenario.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/scenario.spec.ts b/test/scenario.spec.ts index 6ddf43d4..b7b3c318 100644 --- a/test/scenario.spec.ts +++ b/test/scenario.spec.ts @@ -35,6 +35,7 @@ fs.readdirSync(scenarioFolder).forEach((file) => { for (const story of scenario.stories) { it(story.description, async function () { + // Retry the test scenarios up to 4 times if an error happens, due erratic HEVM network errors this.retries(4); await executeStory(story, testEnv); }); From 9e62528b98b071fbf9257ffc908211523a4b5248 Mon Sep 17 00:00:00 2001 From: dhadrien Date: Wed, 3 Feb 2021 15:57:34 +0100 Subject: [PATCH 065/219] Fixed memory usage --- contracts/adapters/BaseUniswapAdapter.sol | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contracts/adapters/BaseUniswapAdapter.sol b/contracts/adapters/BaseUniswapAdapter.sol index 63f8dc52..d1b9957c 100644 --- a/contracts/adapters/BaseUniswapAdapter.sol +++ b/contracts/adapters/BaseUniswapAdapter.sol @@ -349,13 +349,15 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt if (reserveIn == reserveOut) { uint256 reserveDecimals = _getDecimals(reserveIn); + address[] memory _reserveIn = new address[](1); + _reserveIn[0] = reserveIn; return AmountCalc( finalAmountIn, finalAmountIn.mul(10**18).div(amountIn), _calcUsdValue(reserveIn, amountIn, reserveDecimals), _calcUsdValue(reserveIn, finalAmountIn, reserveDecimals), - [reserveIn] + _reserveIn ); } @@ -437,13 +439,15 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt // Add flash loan fee uint256 amountIn = amountOut.add(amountOut.mul(FLASHLOAN_PREMIUM_TOTAL).div(10000)); uint256 reserveDecimals = _getDecimals(reserveIn); + address[] memory _reserveIn = new address[](1); + _reserveIn[0] = reserveIn; return AmountCalc( amountIn, amountOut.mul(10**18).div(amountIn), _calcUsdValue(reserveIn, amountIn, reserveDecimals), _calcUsdValue(reserveIn, amountOut, reserveDecimals), - [reserveIn] + _reserveIn ); } From 5d6332d6eac7150bff2188fb49ec793df3780edb Mon Sep 17 00:00:00 2001 From: dangerousfood Date: Tue, 2 Feb 2021 16:06:01 -0600 Subject: [PATCH 066/219] add xSushi --- helpers/types.ts | 3 +++ markets/aave/commons.ts | 1 + markets/aave/index.ts | 4 ++++ markets/aave/reservesConfigs.ts | 17 +++++++++++++++++ 4 files changed, 25 insertions(+) diff --git a/helpers/types.ts b/helpers/types.ts index 7b2e6662..cf9bb815 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -203,6 +203,7 @@ export interface iAssetBase { USD: T; REN: T; ENJ: T; + xSUSHI: T; } export type iAssetsWithoutETH = Omit, 'ETH'>; @@ -231,6 +232,7 @@ export type iAavePoolAssets = Pick< | 'UNI' | 'REN' | 'ENJ' + | 'xSUSHI' >; export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; @@ -261,6 +263,7 @@ export enum TokenContractId { YFI = 'YFI', UNI = 'UNI', ENJ = 'ENJ', + xSUSHI = 'xSUSHI' } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index f2fdb6f3..6833e67f 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -23,6 +23,7 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), + xSUSHI: oneEther.multipliedBy('0.00913428586').toFixed(), USD: '5848466240000000', }; // ---------------- diff --git a/markets/aave/index.ts b/markets/aave/index.ts index eefcdd3b..d60db80f 100644 --- a/markets/aave/index.ts +++ b/markets/aave/index.ts @@ -22,6 +22,7 @@ import { strategyWBTC, strategyWETH, strategyYFI, + strategyXSUSHI, } from './reservesConfigs'; // ---------------- @@ -53,6 +54,7 @@ export const AaveConfig: IAaveConfiguration = { WETH: strategyWETH, YFI: strategyYFI, ZRX: strategyZRX, + xSUSHI: strategyXSUSHI, }, ReserveAssets: { [eEthereumNetwork.buidlerevm]: {}, @@ -123,6 +125,7 @@ export const AaveConfig: IAaveConfiguration = { WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', YFI: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', ZRX: '0xE41d2489571d322189246DaFA5ebDe1F4699F498', + xSUSHI: '0x8798249c2E607446EfB7Ad49eC89dD1865Ff4272', }, [EthereumNetwork.tenderlyMain]: { AAVE: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', @@ -145,6 +148,7 @@ export const AaveConfig: IAaveConfiguration = { WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', YFI: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', ZRX: '0xE41d2489571d322189246DaFA5ebDe1F4699F498', + xSUSHI: '0x8798249c2E607446EfB7Ad49eC89dD1865Ff4272', }, }, }; diff --git a/markets/aave/reservesConfigs.ts b/markets/aave/reservesConfigs.ts index 68ec93d6..30f094ac 100644 --- a/markets/aave/reservesConfigs.ts +++ b/markets/aave/reservesConfigs.ts @@ -340,4 +340,21 @@ export const strategyZRX: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000' +}; + +export const strategyXSUSHI: IReserveParams = { + 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', + baseLTVAsCollateral: '2500', + liquidationThreshold: '4500', + liquidationBonus: '11500', + borrowingEnabled: true, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '3500', }; \ No newline at end of file From 0d1e673f5627613f9267df9cd6a77a396c664d93 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 4 Feb 2021 13:43:59 -0500 Subject: [PATCH 067/219] Removed an un-merged line break --- contracts/adapters/BaseUniswapAdapter.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/adapters/BaseUniswapAdapter.sol b/contracts/adapters/BaseUniswapAdapter.sol index abe814cd..a36bfe2f 100644 --- a/contracts/adapters/BaseUniswapAdapter.sol +++ b/contracts/adapters/BaseUniswapAdapter.sol @@ -24,7 +24,6 @@ import {IBaseUniswapAdapter} from './interfaces/IBaseUniswapAdapter.sol'; abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapter, Ownable { using SafeMath for uint256; using PercentageMath for uint256; - using SafeERC20 for IERC20; // Max slippage percent allowed From fc5129ec44485c9f15be85b83484e4b44dbd43e1 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 4 Feb 2021 13:45:56 -0500 Subject: [PATCH 068/219] Checked out unmerged audit file from gitlab --- audits/Mixbytes-aave-v2-03-12-2020.pdf | Bin 3476800 -> 4951142 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/audits/Mixbytes-aave-v2-03-12-2020.pdf b/audits/Mixbytes-aave-v2-03-12-2020.pdf index 9b4f39059dfa3ea2ea8777b12b127bc46ffc181f..803d0fd8e4f09340a4a1a8eeb0ed22d661a613cf 100644 GIT binary patch delta 760947 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%0D>R1BMeXF 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 o@T-5?}+7+ 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�o&irnT`n!KOPTs9?`p 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

&= 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

W|B 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

q>i!Oll&v&0=(aEkJ3UIgun?uGEs$s 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 From 39e994f533ab6c0be4d44b256a4122af65ec33a8 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 4 Feb 2021 13:47:19 -0500 Subject: [PATCH 069/219] Checked out unmerged readme from gitlab --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 154b43b4..739ef23c 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,6 @@ A more detailed and technical description of the protocol can be found in this r - CertiK (28/09/2020 - 02/12/2020): [report](./audits/Certik-aave-v2-03-12-2020.pdf) - Consensys Diligence (09/09/2020 - 09/10/2020): [report](https://consensys.net/diligence/audits/2020/09/aave-protocol-v2/) - Certora, formal verification (02/08/2020 - 29/10/2020): [report](./audits/Certora-FV-aave-v2-03-12-2020.pdf) -- SigmaPrime (January 2021): [report](./audits/SigmaPrime-aave-v2-01-2021.pdf) ## Connect with the community From 32ddc01ba98f574398fabf07b37408c18c1caf1f Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 4 Feb 2021 14:12:08 -0500 Subject: [PATCH 070/219] Fixed slight merge errors --- README.md | 1 + audits/Mixbytes-aave-v2-03-12-2020.pdf | Bin 4951142 -> 3476800 bytes 2 files changed, 1 insertion(+) diff --git a/README.md b/README.md index 739ef23c..154b43b4 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ A more detailed and technical description of the protocol can be found in this r - CertiK (28/09/2020 - 02/12/2020): [report](./audits/Certik-aave-v2-03-12-2020.pdf) - Consensys Diligence (09/09/2020 - 09/10/2020): [report](https://consensys.net/diligence/audits/2020/09/aave-protocol-v2/) - Certora, formal verification (02/08/2020 - 29/10/2020): [report](./audits/Certora-FV-aave-v2-03-12-2020.pdf) +- SigmaPrime (January 2021): [report](./audits/SigmaPrime-aave-v2-01-2021.pdf) ## Connect with the community diff --git a/audits/Mixbytes-aave-v2-03-12-2020.pdf b/audits/Mixbytes-aave-v2-03-12-2020.pdf index 803d0fd8e4f09340a4a1a8eeb0ed22d661a613cf..9b4f39059dfa3ea2ea8777b12b127bc46ffc181f 100644 GIT binary patch delta 450475 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

q>i!Oll&v&0=(aEkJ3UIgun?uGEs$s z%=3%0A3H3n)v14*c*Cu&(YgLwO11JPmwa(EJ4$4F?zfi9O+NJR=#lqo@5c)tq`pLn zkAJtJMp{y?XU=BL^HOu?CQ}6xR?HJ`AgeNmbyk6*jZJIrHyO%qL^170%{s*I-f41< zp$15PD$APMw%!|gZ&K)_k%bO^8ln7iKTgf*#=Mc9(PC>mI1iEk-DzhbYOX7QnOL!Pa9gv6`9#$vxUTU2gKj2!GvdO zOhqL*U56D=e?3rye!KKqlLkDsZYR-ie!HB+Kq{#!aeU0~`D=#J|MVu%mmm<8&H*?nqIy42B5sGY+ zEz2B#O^qGz1fGo?jw;OKeO`|&r1E9xOyuDDdSCd5d3rT^^o6pOg8nEv#+Ga0Zt(t7 zS+Sk3({+pG>)hbqE!Z{;&c=YgauMdQM$>4koAxT7|m2(r4 zV&zaWKA&|0rQF*F>DG1avzJ!s;yhT3Ve9gBD>UG%I{QF8a2&k|*Z2OfVzj4cif$y4 z$Wo~LbNX1(MCLavtoHoPL3Mpr_3Y;u?e98}13_m&iQ`Dmi_~TtY?gKs1<7|+zCRlL zS=RPVZMG;fk70Vam=7#Urt`t6*1nXr_+rLRNe(dZ$S-D#9AgWlbR2uEp=$QVpUI-o zRZ1Y|%$qQKwG>sUgJgUDtFMKbA#Tp3Gd*)p^$*VF*kVHid{d$%zIU%$e$9V8c=rrU zRPx5n?{6wj$2p+e7{qrWoc(TY*bKVok&bReZI5glz$ z9A0i&iL#q;Rw++fzmLw@GF$q&{DlIRpBSyui=x9V^v|s05rmr8jMbs2I%zq`t-b*{ z`G6Ru{-6c&?s<}PG2Id~PrRY#`c>3A~ieJx6_3|KVu7qelD_8?0zZg7J7&;jvUv(Q!eRvc) zUrJ5(XxRO!1p;@B+L!ZYii_72Em{`Rlp~#^3>21Ok3brU!q2DIw3bhTcV7uE?i)5| zQ8)`w;4xcE7PlTpn?-uyQHr%YI}2rTxU`uW8P2+~#R-n9AwK&B$)o{20ps0gWp$8Z zu1qSWtI^e`yYpsJr&!gAH#(XGE=ne4zWMbH-%vF1vv@^IZtkD-t1bR*Kg|4?1|z5Z z*mqcxerwGkiX$o?i)WfW@LK&4EJnP=1l4~L8qBilk|5}^aTvY8l$wVA0HG#9^0Tq%>t7^%UZ{x0?6dL7x2a?dqHj@%W16ykC2>n+- zUrD1d-_iqEI~Av+Nr<(9!=CO2WZ8c)!+0v@7L~AH3XeE=lnP%eGGpmX z*CU2?a}5Wt+WryBrcTixD^?@hYDPnfqa~f~3pYVev%Wq>mbA8K-3CLhbp^Pc7}Qxm zSYpQb|74A>AIZZCFfwJW@-J=at~pgF2D$&}jNE%hFhgxal_YXRM^bssMy?&w9ebiX_I5U% zIG{Law>t8#3T}t}w+bvROfy3ZX{!}7!wt<4$vxC%;Yt2Bkqm~%; zt8pu62cZH-9@jm^p3*pKgq9SljL_-5kD6(_8fZPtrQa5T1EIwy;l00^f^0jSo|ZAP zV$y>Wb;2*}t1}E64kD)T=2^A~dF>U0kt~5V<85#B5!C(QB|n{5!QxwzWaX}w zhDl?EKls@Gavq$aG)s>Kb^W^E-zzIlO_&Ldik&*G?pAPZp+GU)op^h{a1Syu#S|5S zF7_iYF@9$MF5$pVU~k2nRw}2(3!(AwmPbEK{Rkzzderv|-0bPIiPmnz+TBU<_q1%S z#N(N;TLE+ocVdF)=;;a(H{vt3uhbI2`eSNbOMS$^~N zBs(<2_OybwQoOx>KQ+o=-TDn0sr@k)i{AtStAk$0QX)9@gDZ*4Cvqck5{6H4Eqzwv z-eu?-fuSg<}S|mk>5FUVScKvYQ3DrC^k~KQ7~zBI2BVG z8&FjKadaKZQe4ZGups_J~ z=DF0o>#vsdmTCz(v-&1vXy_M(O^9-7Lq6zFef%;>7)+7!q*UoG^1MnUK0}o(had}e z9LEB?Ml(*%3gzWdz1>l1%`zPuH5S1swRTq}Z6%*VHpe6rU{H6$FW;p9CdzbYH}<=Q zm>M^=zgYcx$BwvG$$r;2C*2jY`2ce{)GGG839Vu;wZ5N|!FyUXa_{Nef8h{MDCch( z920)+*9BX32eN-(nU?U_n-jWfW?!YK4W57Mc;Z*_Yh0^f!&%9$SaRTmE#6^BHtqMo z+HT`$+pQMcdr)YX4^rq`;(CdOXFTfUIraXNZ-)~@^FJQP%Q*A6oORJB zi>>R)m2dcplL)%rt$i-wuq|VGck}qg)}MyL0@*ZhhUjUZ>=$BTjJY2IL)LKDS4wb_Q~ZzKjm8oIQLWT`QtynQlAdyA1(dt(Qo2?%y^@9r0L{QdeeP>qP3w4w8?X+NH*U2)+TB7*NrZ_E&L zquy;6nba8vcyVMSW;|~6|B0gZCvY=8yo1qw;|^-E^O|EmYICliYfAL`!kV}BS`ue! ze`Z|bGp9|NpF52F zZEVM(jz;C;4HJ1V3W=$ng!@owIxYT`;4SVsS%8TR4#T(x_r(IyvhzJ2;ajZ7U6xp0 z<<=PAD#U2~T^m}O7@projr6oZpq&;(f?2dEEhSfsZsdls_@ReF&uwi4XvX|%?i9OD z>%dyMGs#VBVLSGJ$dfj}L+@i%Pi~0YHrgCiK1O{D#yI6?v}ez!%}WKPI0x794$_O$ zkZongZpN=51-w3gt=Xj2O)31xMZLFag$YL!IQts$x!FarsFLHWE+qN`61JSB*XV-Z zvvZm`J2U99kJKLR)jnT%toZqM9cSBH1O%QyTf}3J8Ne=S^zQ2)f%sMQ)~vO$IfpK0 zB_u2lw7nHT{Dq2IZHHiCE4xbYEK-1;y5W(shpw$V-HhgoIsfbrThUsb`MgQ$S$_H| zDqIn-K^hGohm$dU>`-#}!bOg#YVrm01bVqU=O(X2=BUCxzv1ko!(CPFEox?(d}Rzq zFd1KrKYd9Xx@sY^iql9s_*q}{JW_R3{4hDrgL5Ypii{o>u?6XhRm3t^D)SNLYx%){ z7BQcEv@TMka43m7Jf{~-OKY-gO^@jJTJkKLDLt5)015Xknd=XF;dDBonj6cu8CM(W z_fimSz5M3{EsxlsI0~lS??*qOO1wk>AK!KS_21C^cuiWY7}w#3F+0u-Rv>(o*`Jw} zi&c2MdT^zBX72a$H7$t6)350(Mznm0m3I*zR-!QW?<-73&6m~m!5KGnk1xjmp7g$^ z>JH>}F0XY5Hz0Jl+U8zp;Q+o#c;47%;(3vIdcyB8-K17l6+6`LE7!b?7AdE3!OicZ zP>5q~w}@ZW*)-eJXYqeXp`*u@bLWGsIW3KwflGF~{0p~}eDd}%F3RX<7GoB2ER@BB)9(29GOM+}BY;WkZ3s3(V|OmkU8Q=qF`wJoX=)tw_pnXa-@s^^ch8!3mR(5s&l0F$gX!iH1#VLKTYkO~Rt-k26hd)1KOftvqed;~+o` zkGJ+i%4IiJE)KB}%WVX06>*McG%|CbjN?s0@DG3=W-}Z3$$4S7mlDd|;5_ zt%{BG+dICaAM1}drFtxKEX8;}G8*0E-y7T2Ue}V0jCYQwnzv$kTH9U*;3cHvb1iEI zZ_-_<-e7{H?8l(~9gKzGZ4FAak$6c@)n2QqLKU>^sJxM>M_v(eBIv||4$^qEH~tkT zGswknkup#0zt6qT8&5@SM?OhN*l z?5wUZvk%foi&V^qJ zn-Ip?4U!Dv{>F{|s58LZ;V{%j?IV0VxhgmQCT43JEPh^t`*ovIIZ3bR$v_X4A7c$* z+vP~`%GGnh{KFmDm)O}Rf*mrHR!Z6v4L-;Lw)S=P(PJ8S?j)k?E$WLqJhmb))WHFy z0W@(Bz_tsD;(DFo{9$w&{84RRAZN+%9iqXHkWAG{ZClS-Y+>k-P=7Qbe%Qe$?k9-V zYgl$KS!Jxh>iF^Ve4=Z0tZ+dlT|GJfHt3 z6l*ARoRjmnRVn`+1rpn!63;jtz_v?c+5hWHJKfoI+JsMaDvR02+D1Mw>kD|t=<*RD@n1;a-`fiZ*vBswNfdrxDQGaOL|EDy&i1>>Bhz*y zcM~*on05I60jIwGN9;Tx9 zGj=A1u%&R+GR4q_3m6=Nb(wD14_eBIi-`tQy40`GJVx7TdGLf+Xe zPRB>^;Y?%lx7}V9d(+K*U`5Zc^+<#clp#n#P{_}7Qg!<$+g=Z|t~Vdek4+G|O|}cM zEZnMYdLyL%Q9?tK>|jiYz1TZZ3S+o1m7tr1gjq=Z!#A^hp2heqJW3=_zp_wGd(^sy znH(359-2FerQ8pk)?jens{*Pun|sBW=cs<1i#1ymi{qe*rl2V2tyea~F2|aMZrne9 zJT>VLX>3;@=QgSl#rWJE`+qe| zIEB7?*e&*Rs7(PiFO zdEy#-_h+!gg(!kVGF>4IMYtuXk8-`&O214b$XaE8X8c*;NQ4$-lJQF;brdR+AIXtO zQ2x3VayZwDn>6~1G>LvG>CwgfN6U`GQrTUs3N~Na3@}7_Co%_$Eu3`vefZp!&B^8% zhav}4yGGo-aRS(>1ZpS2(UqwKT@%>u6lASVH?pk$DIR#lqn9 z=vR2kq(QN$J&3A@0YQFPE|h2A0x{nW~XoUA(hE-wJ?+9m$t|GRcAUC7G((5-g^B}-)zr%0x_`Iv50^%z&!!p%&K-fY%ad-Dv>ntR3 zvybuPF{S>=e?K>TYW&AT=;lUh(!cnN-W9>4G(j3v_WPfSwQn!$%)q!zFZrcI8Ufp` ztm;k;@pFerxNTP=%(kohoc0qSjTG?BbU}KgZtlE>Wlzl?vyae(t>uU0G2hSMX_eRE z$+Q}Jb|1^!ISFfB7m_QJ`2A|nOG0#J#2Y$IoP-Czs>hP@h~f5DSt@G2q1KX4-W*CKglQ>nd%JGd#j04gUB#uC3_3`W}yT$dy<| zNAI6Aj*4Gz{N^0R(@(7C!21{d7sq|USMq>fP@9zx#4`XNpx*)b_7gb$4#sE$pl)+O z-l2XELmUa(oXaRzNosKz0Mx2uXks7_>o51&C#X!1{0#5oky^M)wde z9EJHo;szcFp&YQ90vYxL5QG z1iyE3@h@+{&jdnbeYI!M zY%@?LjA#YS;deDA_*@=}|0l-*+@-_e0<6UZ06C(q72uyu6KoWSttALXyUakCf&1TJ zLS7Wo)k12lK!7F&ERY&0j6uT(+4><2XVA=uv%>3W^rhp2Q2VN3Ly*O>097NPNq7~t z3$)e-#DNC?h)>G(&^4_F=EEew2Nb{$7*GMbI2h>bK?+cQ?w^4G_ZFb<%++H{$TS54 zCN$d>Bn&6Qcm|6I2dN1bcwdlv&|~nt@0lhV`L1EQU-J9gHjoyodyVE7=PXYIF#4z`qc(6!caQ znPg-Pi12G9CP->F+cPL{Ac*7N%vzDcc~s#sbb!8!!0Xuml4&f!;(DT4)x2nGQ% zML@k7d^t`~@(|E1JdZGKR)B0Nz{d|cwNnfRlGu7e1TO?&70v*Kgzlb(>*n92Dpdk8>s3l|13h2MUV!>R$fZ}vI0ZJcj0~Rg>ITytC5D$SB(2vT= z1zr6MATUh#zW@l%tgw}ZggLW5>=C&896*o5gLD^wSRVoqJ|zNt;J&GqKvIPz$RTy% zDku>2BG4hcBA6K+z!gnF!UBYw;N(u={Q;1QEgI zVu2jTq5yS;GZJKBiV#8iR7Fvs$)z9x80Qc;&|wyJ!2g~MFl`xFN4PB*P@)A9KV+@y zzi=~MXiks_6KZBiLpO>ml%NL0_^|E|esn+tz>n@h+6I_yV0eH<2)}@DUbr`yS^dA) z0I;TWhF;c#Mj!S)+?DQubIJ#^r3-;=n}B~a1b3v{^6a5tX1Hwc@H?-0c>G_ zeAx`*e<s7wT%-s{ z`@jwX*rlBm`ZM*mJTJ5F%M+5rh(6tUX)E@aJue~~OQP&c ze(^tydFGeNkQzL0kGTAv5yPuh(eG#W%e~Qk`?GuB?Kf_zd25UOiu!w=K0Ra7E-HNS zVMV^NT+@#jaqsjd5t$#o+g^<%M+7fNcY~Xs^j*S}ztlN3Z@{V+_OmkfkIpFHh@ZG( zV=I`M#RL`aOW9irA#zr$@FsO%p%Y_ysLl1D75peqg>9PSE7M z=wGpI(dI#WRUW9ql3}T}iCT)KQ_ww9~f7qEvjvZd?=D+Ohj&>d9`Yw@@ zjy(pTweQr16!s()#h_?3S?0R*NvkNyRN55U+MH& zdIJqv+xuW3-H$(BHA*`yJHGVlZL0et^Q~7kTqFs*ayS&LzbrhP_`e?eBIw8KaVhhi z+#DqyA~tZ*IS+)8xAKS$nGW^h6#wmQMSAhx)ZS>A=F%+HULFczk|YV3O6RVhh%-An z-0uJVoKfPLD|m9{Zns}ubWv8GGVGO1sY7nEn>^CN7JqI9$Lp^a%T&-HZ^}oJLoS>u z7LT$TKC)Pug;}U2|5gi4_vfGSi;Ht!i@Y&C`mA%>N{pJur+TI&W75LvX7)KNW{}a~ zXVIgKuO#}}11jR60h!%o+uIiLR-uylnOcoqjOVjxt5;xK-p#caJJZBgZP~H9h^FA# z>DDgA0l!ucY4?hhFKJiC#mLaP46}=N_l;4fV#oJ;Q%8rJ?%jIgssc&PoTjeS_RtrV zA(B_I)_2UC3?!}g1!5>6Pk-nYQq8q>*EBY9+)L=*#lEV3EixiGuN^!zOtA1>IcZ1i zb(*KRt;Hmm!;_Te+^;-pGSXoxQs(Dd^H?KpM)c%v`Mai>GAd<6C5ooL%iWc6_Ppcm zN|r9lpRVQShHK}qaYN6DcYR#@PNhsf;@4BolLhNjmhn{~u*A#f4H|vESRlAlvOXeB z8z#-Qj}-aLXHkbjajaCx9Er}iIwr^)o)i{Zi&wS`?%=o+X027BeDbB_v1NGyy&Y+J z3wa#Xfj>b_P)HwP+3&y41==i3T;xj$P+!ch-xU_61+{Lb3h6t0ffRm3jfs4B=)s|z#uPH=IM$oGK*ey&d0ex=2LcV$~g(pTr zdMZ>*5F9c?gnGTTTqnHVGAMK*SGXT8)knFE6V(DE;T}ww7c1TPO|OsvpY%F))|Dzp(bVpGyFiVe(!Zx)sRLt z2#Z;h`Hxodo{5fl`=J<%8bag>t|$^)}LNnpS?rR^Uum^t|IH%ZzDjj#z25=CU^ctVsiqKi_4 zYG^Ph6fZtMR%UGMsD~WSf$G6+2Fb3HD=g{`8MmyGsI#_?JgMgwn9NcckYkZNHo{1k zjn760l=#wt$9)=eZ!HEE`s1&H!prw1CD2Rx(|u^Y1Bb8K^QrkYZvTiMSVUe1Ju2mJ;U=VEg#lgjnP z>loE3qn{9qd=Glzq_ftFrXohB*b(G$k9g)5w;yogLPMcAOAIyQzf-My%F@Js#C0`- ze%2f@=Sd-K5OK>H?LCutXabsO^1?iR%xTlYO|$CW(jY#11CfI$2lk4D#!6Z-MrZ}# zD%EBwv&IGaQvI3iCjJ9PW%Ydesuo{miAH1>-)=rS5;uJJQ2@^8L;h7vsUl{InSuc) zT0Eqdr*y_26ZDX19Ll#kD^mk98QpxsH6^4FQ+hoSa3Wbz|38w~RRDCCAJ!m5` zZ-sVE>uo-`W0;3mf+=ynyA9|O#bP&>#!NbwF6dth%v~mkVU5T zXaXrqWLAfwN)V6|a4<$Hb5?iT+;J;<$1aqmz_IZR8iG&%hxaf2E?p|xZh1i0tb1q( zKB5L&*E%Mh21SBCt*h4Zw6<`b^QXsZEptnLpf5Gcni;nyvy5mHs_4$16=N!0ikbp! zqGk<0CWpB^CSMgi&ok%8^hqFx#0FAj(n!y~C(ZcdIDI=>2@XFcW{CQ6>uB9w+oEow zI1m)8uQ)+c_axSBrh<*vzB-^%|7OWvU07o>+3`9XEYxgc(TY}tt)DU`>t!(dvJ)w| z$k3k-0nNtMat~=>M74esf)}vkUd7dWzO?tvYd&y}{(#Z>i>(f#me^c}!97pRQmG5y zTd_WgAe)|-Uf^lY&s^2HgBN<3bBI_jB&75c@z$o#%=v|M`!#+E-Dlh8sw8-n8e@9x zJYErTrZec1dn`*!rjCz__>BldlKttG&0Bi^)#G;T4DynlA2oJy9We{thl;e*Y$#)_ zr+dzy{`yAf%e*aqKX0STmo>plb-MF&E|%+Ux0v#|S+yKkkjO&NbYj0a`C|KW)Mz{h z!}lj6tEvBaal5eARaxmUd!G62;4gjV58UiX`TL!mXHu;GgKa()6FJ4$wt}tvR0Xah zd)W3V-v)|5gdGKb>F7(gQlXMEnN`(kS9kIFOXl_O98;dVSX6+K#6?1-+#l{Tj-JTTfKG;a~Q)QLL z`cQXeMFBFT57qmgG#{yTAdE+AOKFO7%^Q(V1iPzGaKgW%A=}SnC2s~ob ze8+)No1NcgF^-PWKZ@Yqj?naJhH*uTuYg(0r_i)az)2^Dv5i`kS|cQ1AalL{fdI#+U(<<^Rwd%7OA z^u11-MT6k*pXnmbBC0s4n#6UhU^2v1OR#vA7yIe9ncIPCCR#*cN!Il6_p*^z)g#h(CXq1fn|FLS@d zYU<*VEJ;5f-d!F|Ikg(pWTdeghx8gDRAApP%Mf2L<_OVqVKn|4`@r*l#%124BypZ> zf0EC%De$SZosW^!Z-Ej+5-X7Nc5~Le@HwR}=~p_^m;yc{YyIENlp8I#$f#eJ4x($t za48$DC#g1k#3Cd|AY0p1MBqyKcdXnslFC~S1aXFyVqbr|664r%d^P{uycR$}-?KTS z{dJ8KWA9YB+0=ZDC&=Q)WASC!Oei*X{d}XF^3doZ&dk;cQc|akS?u6*i^V5qDN7q` z+{C>`t4)`E-lszM#zb?-&aGaQ-j@2Ypq0Det8Aj~I+eOAf#%8J@-Z;e>fM{)m-oRF zQ#DuBZ$W=k5S^Ipe-!83s&V#khikmpE+)Gx&#eP7#-ePlozB&HoT4vQ;QwkvRu$N1 zeq?_zyIg{lVxtkx*UlQmD=H(MW88{vljw?ByCw3JcU|=hg+{ouNK3l$i2H4u=o~6_ zH<$EHkpkM?7@mB>grEX=JK%ja>&5(H3q~Cz`fY16ZZ{72;0=E^iu<@-XdmPg2 z^<@VkK_^`D?<6_|OdkD#wohmOKc=obp6c)aCo@~zYs=nyW^Wl~6Us~^vR8_0mzCYy zEM&_{T(b}r*{fuPLXugw^gHi+_4)q(a=q{Sobx)bGv4pVc|Py++3{6DZcvXt*u|bH zHG6+4qp57}Wu5KQ>k}F62}LF`B*#AsJ`GD#S~E^8I(pL%ZG0~z@kG%R%NPfohTd%Fc4JTQaUg=BmWY>EAj);%G68vH z>I20sZJ+x~hRJrKM7YgMZHD?alrkOBW#2vM9-i#@PBycmn#ELz<<*~Ro=33J8*pKC21LP)Mb)ndz=E-|8GWnYm|e>wFWg|>^Ea<7w7@Gr@)xJhb-gTk)9kJzX>#f_ zlXMB0`%?J+<%Js^U4}Xv&+TSnbkZe!Xx|JKgc9GliJOsL&LBX2bR%`L#6K*-WV?@H za1!qk1snGdi;RxHTHRL(C%yz1Ge89sZinVBM&`bjr8Ou7UiRnvw}pNlL`yoj#B>H` zW&;#E1L5F4%IFlt6d+wffPPCJJWLqu!OrDa)gfs^q!zf{t&Q66%@`FKe$T1S!Jq4M zzOM2tzdHTB68`sooYFiqLrrWAIKtdiI2muzMqBFR?lEGLG^}%e=|+8VzNJ~ceUgd>`oGBusDA0ZjVcJI8#)k|(ht+X*v=J$8AicOxx zwQWX?Zt@yEv6e5D>A!|)YU+gxiXT~YMx$~Q2G$Eu93m|W?Mj4q@C`CLg&$HpU^nWp z_Vt%hp1a`dg6LP_7qap(j6YoXTuZ)>8x#KHU9PwB)tf^M1NCBwEg!5W3+0sK>g?Q$ zZgkIU(#`WnoO?zb)B5xN?n>W!)$^QRcc~fpFDR~Gf7aYBt#^o8iL4-2xMiX(-HGrJ zGvVVXYeUu3I9%aAYOc}z*43n4dnEN2O4Gk+X&hAJXMKaAtN)Vj*B=pvO6qN-hpmG| zduG8s)6YeYYS+v8A1KF9)h$Q_l^H8=8`*k@4&ri1_}_@k^f3Ic?nbm5^Y_LrkK)T?KJxlTXB$fcOsX`P z#qEX5Lx-;L))Bmm;4h3c9x2i(EhfqvhI(~6ul zIg__X&RA%qiwQ4!l@RgaAsS5^qQ&pN<;$hN&Gwm%E`6x~?_0i=Ya-trkQra9W2$_U z0E(UFlrQkzoh=cv%GNhx`sG4bus&zAb+AHD$>%-tP^)bz}rN?6CZz2Mc^LI=4mp%mw*R_z? zScnP>%iYvCQ%`9*l1j7uq(Wyk<;2X<^x_$P8e*P)cSIhCO`gfYFWvMjcjy#ZNW5KK z*J^`NskVnWWC7`8mzAU3)=dqx4tvAmzcW2c3>UqqJ$WDEyG-i;u!X|qRloU9n(%bi zfvTYg9CC(H3B8wZOx(*J?3-iP!a4CH4)OPm`$LNe5`JIXZ$swXPEQM9Y>nYg67_hK z*%Fn>;u?vDk+VPIdbmb1jO(p9)cfPKTWgc)P&8um%R+{}iT!dC;q_PL(%tM9{^&OL zXRxrcalX8wIUTKivc$}Xu#n|4Q&Y3f z7a^A)%w#Cv(&Q|1m8GPvmF$bn4gkL{_GFNFt(SM!(e=U5hT(;K{6WzpL(*?vwRlb$ zC`qY&G>gO~x?;B4;qO&Ooy>ygRCtwH^z6U|+!qlfH`j{{$C%T;6Gid39#4AJd{1CJ zBbmdnN9IBvxXpcUnw^+Qw_Y#V@PQHTnSpu_qt&@Ls5}ut;O%p7Ni4Fhw?~5K{n%Be z7B52is4}zl@e|XvVzDL`4tY*_yUtl&*(TOQ-^Rx;&hLCS9HqNtFl&45 z3is~!q~!YA<-4O=F>Z$V?B3sLw@4*f7bYoibFUIk57}$Z9)~&pNEqtXy5Tuvu?ai- z^z&HULJ@i4Gjg-!yfbvMwp}u3kLOOPs&2Q6kGUeJMzur@TlzA#P!V6&%|Qs z)non_+73G34=MM}^j&hI-xb|vJ2FuJSkH{WdxCSOv1eV?y`0nG-Hn>Qo|4=(;rbBG z(Wo}+by?H&$Hc;w!mGQMx*?Jz#{NCo)CfPXof7r$@qWA_a$oo(>Z}#5%6o3GC3lCC zi=n<}rsGAjw@-qHqKzSm^b7SC3L&z9%)c&Q11k@gg-|o^{%GELBDmzGZgq06a?9(d!_4sq4(oz zC)`X9=iHnZXue%?i_k_&J?!ASq&dPY?CuI`)ro>_d@+XMVk62u8tz(q2cbP&q>ZV76&eIbT+Hp zwc~L{kh_>hRuT*nI}FS3=ShtnvdqevcHSkh^(m$&!p|~J{EJheR4SFWuN=BFMdDQ2 zjpExf=AIY%(a7{m=!3lF;|)r|tsW-AOPj4>(_U*AYsJ2&#mlhIex$AWKHDWNR71cO zaVC|~MxgtH;e*z>W3Lo5n{H&Mkeh; z?*jaxQ9%csEUR|wV2gpzwWe5{StVKxhQ#eJF~OiWI31tW{)ZC-34aX?P7DCEeGEPT zK&*ZhOk@8K-USzrF)%tPO!6NJ3v_0z{}nz_1)ws}zsNhiu=NdK(X7Q(FaitW2H-CI zbw`#W9HeNhnmDe6xD3W>2K*m-1?Zf>a5MO9q<0!6P6|CnHfC-cfkBb&*G_u|R|G@; z;KUs0vlJ+Z!WT|qet-j<1;Q=hLTxt>3=o5pdS!9cS(7Tt%FswzQ^ zX^8a$8>S(zM`{4B1~mXEA5%kZF-Ey((@$O(z8~Xifd$9GP0xhjn?NdF(CWcJ02?0r zzi|UHBpDc#8l;aI8w8B%gHFybB4Bm`2>TS!XWImj=zn!$0ezqeqzdeSz+Etw57$j~ zLHEBr)!c=n0pqv!ALtL%R{*Ausdu=Z7M21M7sJ{pf&0RWfZ`4K3#0j%TjtrYA;D-q z$Oq_`4-7_wSW#>+m<+DWO9{$D`$zPgO7=8jBZ03StLvXKAo+_ra zY9t#BWrNI|KM#8FhmjasY30VsKQOYpK&)h}XmkxeVjPBlK&1e6#a1A8q>iZo=i$HR zG1yh!IRp%;ffl@$k++~&17sG&+JwM^6nYsbA$dAwHmKi=mk`ZJf~dxTIvs0Z;r!Ef zAXb1u9ZC`fRnSF%ZJLn+46~1c6yhfmg5g+@4*GOv~;e0RVD$s7WB+9s*8?(n2-{N+MGxLN_xYda?Pj$KtXeFf3O949_94D&!>( zq+s&4f%!!#3j)UFzywsJ1d-?q5Tn&EAU0rZ50nu;4)Yl5BdOGF2SP=a9A-& z#gXqEbd?=jL#o*BEhzn}E-$2Fu6`RG!GXwwB|5;O)Rad_Lqs+a<_;{<3MSS6kXFzI zEYd1Uiv-d{RtVsP0_w8Q;d6nIzC4^zB87%46i+8h47p!Jtiajm$XEDZ0>nJYu-p^3 z(6%*P*?ZN~kXnGsOC+r}w^(X_p8Fcv_c3MmSqXdL;fjCI* zPvfXf;Jt;eu}84O{2fpefLTG8#eBfhZm&?f0M`(fs{@pBzyfIk7GN8<5b*N~%*zyB zn^e1D5_GByq77R(e^e3Eq}@417$NrxIGr{8AZ<17+9Z&_7XoIyfGYEWz!b*6jM5u% z9rG|3qxyfN-f@Kn(`g)WBsTT=pA#?lJ9A!RkL^jN#reXQxfz;m}5JwN}&i) zV(`@bw^JtLsDf$pSQ>O$B@{3;iUSas2U%?t7<&xQh1Q242ilw>q=eQ35nY(*R4b_A z<@5N_>BbahMT6OxIv%l0K!ZUDm>~l8^-BOJ_r8bl#CBe_i4VI2bPSVVSq5;<#3~Wk ztv>k!*o{uYPqRLsfDbkzc+x(LKon!9o@W3PjE;jLxWN5S77J{>9EzCS*P;=kkmJMC z;$q=oyfIEx=VB1n*fsA(rV5Xo>Vnj%#1YtaDwME=ZNQcu7LUNpdR7A@nDwxW6;}e{ zI%dI9nIK{FpkY!{;2;Jf$d}{9Jl%lM7Y{j*2D@{C6e>$X2*Pu7cuC3*O1cENN@~f7 zO6*=m#fE9x=q)jpV+416_&^z6uSPdvJ+4M#N{AurbkEt^*SUqR%0g6Pm&_JWX2De4 zOZFc_DQsN|JM1{m7(^jEdloV%qVROZsXjV?3(Zi3aEIFli&GXJaljaZAI+E#7&$cX z4Nf@VsPL;>w1VYMLevS$le9ha&QD7a<7JKJW&?vndb7|zSwKBiUB$2b}VXbp{- zt6&q=26J^24?zMc-{7i1i#H*rFRH;&-O0g5dxxr^%MPwUhb`%n6O=3CAA}M z>TAXX94;@3KhbGR3 zMLe0s?Bn#`3>+zqER4S+W<2!Ryv0?w!MCf9NtNb_R|uk7=<&`w3q8zHbWF1N3r)w6 z;5;!_yzuPuH?*)5%Uk-wzAhQB9Ek>jIsvZV>jKN=xx2N!OBW{(8X$w2zIz!Kj6vv+ zO(^rJnw*F-0P4 zHE#4%0rJe_gZc2}2N#}*uudQBWymawyxTZvc0L*D>q%(GdGq?~FM8Sc)Nun0!Hvhu zHf6D^X<_G`9iK=%x(keOxA~zgqWH z&VFSi`}|g@y!EVOVET5f=krHiMo-rH2ZPV>>fg>ja$=nwbZ4f1o}MgGE|rgCX#FiX zwfN1*MA`@Xj2XID&S%DO7yFyO)U%BL)VXo@jH3tpGR+yg=aHn(iwI;NxT21Ak3Y|? zHdsAE2@FoE4fG@pG0^tlwwD)`&qlEnT&sD&6Fo|2s@ReyYSZX=b3x}u-PcC1l>+V?nEtK zoOMy(88A0i+qgch@?uKoD4|WX?oPIS!>LAl~g_Ytmk*K$gWYlk+gZWsni|=dR^XM0)@nlmpdlX14K*rIU{rz zi+3Gvd5u_3JaDahuohC$FQPV+(zIuXrmD%?iuglPSnKZ`&}_pXfcIxe@W`(_w^|@A zBB}`0{4UzVo<6`>&1;LVP~Eh2P3I_C`zd#9YFM|~vn#K!2Iw5LgrI-oxNAvVNg{v0 z*fDm*nYyR%ib`>EuN)A0{UFLII^8Kc%88&j^NCCGpX*t76Ky(4@7ymv8(5Wj@Jpv; z&6sV#c+f~Bf~hRLE+Dr3?)oHJu(e&B0B25P1x3-3y6bjT&b%p_QR(--Q-=wYgo!*o z?Ny{@;de3GI|F{T6JOCx583$p@%r-vY!e@}1dUg+XiAL!n)~x3tl3{Cc;Vo;SB`AE zk6g#rBju34N+pJrujB4}edfwo#2Z~$NzHg^Tp>mnR-eWx;kMtu_i{$svO&aEjfhY;8iiLTrF;+s)p8_Sx1e9z#s&N&NW3K2(zO)U8$^aLQ$wS;Q zb}kMglQbo7zVSYl{na;IS;w3AV^})fY`XA_g5=YAuf|_-5w)d`J30%<4wmA1J zh4-k24AD$vPk(>aTm4mgthdw_?<&4zZ%Xeb=KU<#h733A}2u$@m!e3Mj?;nY>jp9?{cG&xWB_HN!1UhUU*EJM?M$t zC0j&=FRm}%wi=JrlSzLn5{I~3Yk_96CbcaRRjk2JsuL}JB_Z|+ds3;-cBqGJKK&hK8Gj@wfbm=u6mwmHlE;o zPg9ua=&-dS=J^YjrZ7Xs7Z=pl9{j@h*m>Vhg3>r+cP8tajN#3TW^aww2xR=#If}f6 zGAGEKGRW}w-_Uz?l3a?I5?@dH71q|AWks)&deZ%3O+BUVx?#rREiY6DkRmV@1+?e96iE!7{8xEAgI`#tIOg%_zf zZdaD3xE{BvF+inXX2pKHSL|3%#&~z98jM{br}?$;UV+Tv%_oW8+)kUP^_AuY^y2*n zgaRnW%ckAqW(U`xSIv<-B)1X1Ks?)REX)ZpBSwl#Fqdw!)(wUy2(d{obV$m)l(3QP#Fy zbF2xYyk2%EjyGd7j?)xB(n(e38jX%HNC~xh9r)iJ9AQ3S)XZ#D-fsHq5z*(Q>5C3t z@RutzdV_QrR{G>nG0-1^i|6tHmqD;LYG}DZTR6BSx8e5F^fW)`>DUAJoA36`%6heff&E0TeR2f&5uMEFIJ=%@8#4cymJQ@8^a>ZL3xHJ1)|O zW2r9aNg6$;Cl%LT%QB)rzjGy7Sqxukh!I95XAjY?@+2F7P0t;k&~du_tKzMy&@X#I zAKe)T1E-Bw(T~xx^1r*%%E!Dil6s@dKiR|wO@8K?>VEaEZg1SCJot{YY0*Hq<+Srd z`72S3B3EuPB#oNVOFS26MM@J_*j~Fi6kBK>R3ZM>;Qr5d$yrWgk*2#o)h$1k)C_tv zr%|iqH?1pMB0d(%Ny%JZuzrTN)v=lG){kedBOa?P^ZoK!xT)IcQ-agrt7yc248$Fz z-*OM#=|9Y96L6HL*Xmw_6Ii*`b+KVqZ%vX5G1xCfb0yQ2NHFawktx^4hcCh#TX(DG zJ%j=;WZaYtSjwuuHEBQmqBD?2FkvNnK%W`4SIqXHX&{jBl13&|>892D0h8aKp6%Xr zX3!fBxxDt#sKD?@l0|jGsBBthxO?KOVZd`f<44W6R(7&7uB3WB3#2N{%!_>YMWBS3 z7$>zr$}HpYE!Wk>6(_Im$Zv7gK*l#qGj*!rc|AAFAS^GF& zlc?O`^@j!qZwJ^JEmhc+lj*}wzM^=4QP!);q8@~Q9r+Z^Vf;z?_pm_fu1|3MXF7Bc z=a3WGV|@k{(&MvZbj_waM@9;KJ!e{Ox42laaV*^V6qp+2r1W^Vd@HIgP+5PVrea#u z?rf>d{Qi{f=8b{H-FHGWCqdVuIj2o_YYXqwr+99VFU>N)Sm63{V@rc`lB+}qi41)Ba8Rt=@GbR^u$bfu%e^l&^9AOk{?Qbr#hZ=omtH0}e_2=6kg0H> z%Rh(q^vLy+ur5FR!^uR`x8YBV*uM(7j4#yO2*5P~1-k znZC)hJ9{Pi#v&b|s^8K686jRfSEQUsG|}x>P^fm!Xs9S4!7RWw=#zauYyD7Zib24I ztt=c8dnuO_|9%mQy3RiHS2lHHZ;tnWWiBZpSVG%`KB?>ed8@?qI;zM66?skOlFb_z zH=-tWS@PEhE)Kh+-;N&d{TBFeZtOcAOPSX<#gaR7oxPve$)h|a#f9Gru@8 z=P(Vmxf9fuizkt=^J7u$N0k)52Dd0Pow=%IpSz38@uI; zdomS&7C(Q~8))LK@%>RGfhtB23~qe*=oJ|8!~nH-fS(#4C$3o2ZChoK>9aRCXfpUz zOVD=8o1DkF&BaXM!r-?*!GveF1kR{_9cSHVIn(s^QKTlny#Mop+O~r!KXmva*$;#4 z&I0o7g8IHJpD(_z_3y15?yA53bC5Li;8Ucgo48hk!42!-qkFt`lqlBKL)H#8bjR3d zpWm*)08zQG`mCx-ldQPN?-#O>WW_5qWU!Kk4GboYB&AcnYI0dh-zp=2w@v)N0@m<8H z$dL1Sv$y%Q=Un5NosrMOBrYAKiwIl?g?ruF5+-XpCO+h1+6Dx-lYBIw$EnFQ98D`XShc1G6^jh>4| zk{kBjL)pD?;8zySto}Hl(721<8*n3RI9NPPL%80@^?*Dq2AXWEOqM;rm{6~&gZjg)7tbp`x$Og+#Qj&gphnLBe!|0W$)vqr_ z98!a%k!7|zNtf??;FxjAwi)}&rG2;TW&d% zIXvBbz-WAjlqZg!IV>q7t<64WM=eYW)C(^ z8v`yqkLO+b_|$N7dRkM^o1OHf^fxuU>6?YJiKv;e;nEq-X1bMmI+g{!&IrzudrrwL z-yQ}P(wIWo8X1L|P0MUAYVQ+LOn z8~?a|BRDE15t{G?_mVL5(CR4V| zZAvtz`b*c^&hp^>KrZQ4ysiSzuGW$<9Ek&Zi~Ap+hjC{)^8R&_XeQ7r=={BVTy`nE zej|$&m9~?AO*fj-kBC~F_=D6;QQmpp3A;K2e)3L(fw3RD_ElbyE4OlqNq9+iVs%+v z+*GNi{BmFWt?jElXhFWa>lsx0+apYjw5)>EGH}>PfbFP;yjXLTt&Hq$NN7*G*CvA& zZz<{ZGWGj28i%*2ai2zrW!mnt+j6VlboErjnLyd5IvC;u^M)Dd%4R>!D5anFPpb-P zp^NT0%N1ie#GlBJcGqNmRops64-A+ezRN5%A$r|SBK+_VrQmd*8ZmLuLSe7J+RGGU z>5`j{-mM>*XojNwOn8}J8a4`9W>6BDY9w@)Mf;K4+oExt)5H}_(-jb_b7_>B>OPn4 zzq;Fr49R2oEmo|>EY}>|!%C!;`%Qc#`5OC2m;czcb^P>2$d`C#uI{emo2Vb0G z+}h4l{keH^iiHVYnNp30c**B*T#p^KSTKflpf*jK(6fA@#MGBaH&&Fo1IvuR4( z3T4RpO}ryk^1(i~EVf??SI82EI<{vfX2~iaOI;AJ2u@Vvre8L_Wo}l(%d25Tms{zx zq>s85f!|=Ix1kwjFEmpTaZsA`(jVy{8JS#&6DzpToieFAK4Bgc0!95C*U#^}w*85$ zxkSLrp*CKp@v*}Q3V*AfWDA`r#ACLbB|Md7VYba(`-Yt;|MUE~FW*P`OC0r&BblnR zI&H&K^4PoN-pa4~bd1Qym>*^(=iD2ncZS1`ft{j3e9Tg$qFeBAJk}noDjVv&%{TSzd_g&Nih)-#(eo#l^WGq4Se4Fpu{jyn z$TuRRZqu*k5x_1F_rX$MkwIi z{noT7-JdD7Gu_F@n%q+Dq?d}g%aCNxP_;Vfm&wO5QJw20sovw)(^Cu27iIqtMR(sC zcMN`YwvN|d;8NGTrb|}|4I@3}i6+|ftnGNU~cC9FG) z466x=QN>d>YH{-S#{(oVzCqBU2Agi^$c31AO{E#q{hSac z3)M8GUo~b4$TA^T#T^*0G|6psPSAh)g0hlGi$ik%wHb$ES_hkx>i#m>ye{pE?Gtt> zlEkwCBzNyS-ia>=Tz@C*YYlW=gg$r6pNqSq{;hED+!lC=+#1(YJ8wne19V+d)^)}U zx3loZiQK(P&y~jCQ@_!(7Lp2~dRa7ZenDNmEL-?{m!Obzbn^$6ARNuta@ROV)#RQg zL|Na8bw7rvxypMTkJ@VATh>dgKT8g$pTo=UwU#4nKwQzom&j5gdT9M4J-&0irT4{G zt*rO#F&z2wkD;JxgfOa2GW`*OFo%h6@Z+otPO7~FcYO-jMTAk!kpp*Qw~NKDDjiIG z8@|q+7@e9ny! z!J*Xo}AxQf=vB3s(PEwDthJH zsnj!}6d02NhvRSfTk8|qu6S;kx%=7MP%07tgOaz2LI z6aZI7QW~R+0Kk{pV|GT2$OR1gh;56)ASt+eghCqzTmX)XA;d^RsxD$M&jX-04yR5{ z&~PNBE{sNP#UuZbO(en3y)l##fM!)v!r~OFu@o>%2$VZy#?}p6TEWGx?we^JABR+xZ>jbLVtBxFB_6~V|KRma{1ik{k8!6_(KhEu}Yst%|&AnL2E zrx{5ECQ<<9V&}jX0wC-zJ2q>zk*D-1@O@Y}hROtP1a4uNW??@oOezPMVEzw4_<)xc z<^$F)4CIqk_%uSSUD(`fY}*}o8L(Br23Bw|TUM+v!$$&GM!kgfF~F5fjFt(A6L?sG z=95JJ3lH+@ISmE)g<VQ@^tgHqToz@}kv&C>tqSvWTTr4R&I2~*KP zv0w&KfUC}BV|ZwwC!hXD_yTwBU~O5#w52iRili6-8M3bNkwdlz2#hdBz5(GWwPEJ~ z(Fs!tx13+ zhXH30fsX(Tc!Q3lU>PcKSX4u>^%wYn!wr6zZg`%79J+rF3G;wJfd+tDv+gl;qx*@G z8ZclFR+Rr~B{(6#I}BXt*b&DVBH?KO&YKc75yVY{q27R=pFa!aJVq3V(L-cNB<%G9 zuJLMOvH_gOFeDkc2CVxS_yF9;utFgeG^Y{NBF_TKz;|5|XkeT$0}{PX!vI+zkn5Pb zus&p<9L9$X%WDEb!$xG_qCEp}xU%4*Cx<*~k-&%yo>i*SXPwdbbjZKhglsWk44y#W zfe#s&T&g!YFsbx<3NY|cB_stT%!I@Y3=V|`U>|hJk)q!+A%`)7AFB7k&Vgl~Nc?jo zgJZ!sl7SDfBN=4SK?00(xR4_72yRhXe1TX@?xRO8( z!boB4AY=eC!yF!Q@H3gz+l_ zRZ&0@;;=&-xa9Rv&IO9S$;JuS@&FQYyhMf`l0a%`>vy`Pz`xOQon6>BdkwESz;@ME{5(^ddhaC{P;$)CtF)i5-VYFSqz+Pkg zPfny`35gl8WG+yn9Va0Aq{|{<#tO*4JMeW9k^}1jZnBn#876B;{?EetHr#0SFV^%E&30v;gi%#;|OLMKxgRouL@E9Plo~EMQ`Y)=~&d ziz34X3$vMl7~QUoB*q7M1Uqjn@GS$S@}+r$p^OtG;Pii+F+dP z`c09R@azEn#hRE&{%2waT4#HLo#)9Apk^-R6}`gocW_ ziJ_WR9wu~_1@bFArjJWGuzCD{wr1dY3vA8c;Oxt#PY1U68fIX@BNVnZ!wjsF6MhAh z_mY4R+PIEf0^6*e5Eb3&3Ieg?1e1Yby{ZSaE+m0u73}K=KI9hzt(i?5qzqhrSf%v; zWPds!Q#&L!>G~SnpjSpU(l9L%WM&OE3X{ZmoXv571z2K_6anpp%23(Eq$^@b=#>B$ zQT+#Q$_RKnN{zaCMM<-32j7`z8`Y%9*30bw#h; zMBc^D4=)ilu&seaNbvk46H5MPd)9GPLmc|DLrV@Nxu0eQV}3SNtV#+EkfavDU~WFD2(sfX0j|PbUP3!48FNwMs*vFdl!j^nJHT% z9I$ZEV-3K{fwhM)Zy{J39hlRBQle1C6B05=Bp9XwE}5Qal8Z zN;eTcL|Kl^#KZ^OQQ_AINhn!b9Dc@t4+ENTUhR6pfMDd5`YVu_*DkLBTo-6Mh>+{C z0H8`HrPB~Y2HCRb(KMAvXKa?Knp81a-irNattbf@jc8&P+WeuMJd|IJ#IQy4$_QN` zgL$SbwCJL)8xGuq4r6+3AYxf0{~IFvH>#M@wa#3kP+ON63FKIZ-5)~hz*`xHKzCAy zyos6Q9dZ9Xcfq19mib>b9h7v~oyUk5ybpz-kr?GP6<=Dr$9A|RP+m1b2Gj~pP~iP& z{({WEr#F})A62>zy9J8t&kGvtC9QmGaj+9pbvS^-QZsf)r3HF^3p*yp7ezf zrHfxvW28Ra_V!=;@R~yTr2E+0Q+hE?0MX{D!z_EaAV}DBMGJNE>b~6lUnhjlN`LlP zOZ2L^zb!oTJbGyGl-yB$K+L@Qr!e2sXFd&$46^s^&*>NDth>(L&o8|_eZyejrmnZ- z`B(JOpQpzdud6jo^qP)0qN@$VeIh-tvVGEmx+Yc=zr4QcS9j3=@I>$s^{Z1^6>_vu zX8F__;=+C1!sIgNChC3nH-K|8$ zezE`jNG5Ur7Mi;O%mi2B3r;{wE#EzA!HA4?lMXvE2&1UQM z9_a}uKe&gBn5|^;yDL7kBtGjC(L#IlS&`u-!DSAbc@`R?SEw$s*!`pYi%~%Sr}YT| z2{A76MoJn2=|zY{Tns!ce|gcKs@1Rd8&9{xQ2aJ=+)G@Ng6e7`9#P)Uhc7K!nRji> zExsvQL~e=-8uK+6|2DwYVrnN6$kP(-Wf2uuB#+0l4o5xdqwConvT%&PE_Zp!(ZjWzcF;!Y*?gdm$#^dB8{i?+KS;Wmr0E&uNrO%F7fyjPQuR57PV(TRXK*<3~it&Hj@Pfsy`G6}4eId^g?C!5pQ*|ZJ^Xp$L3BmKdE;%_VLD0NdbNnX zJgS*DLvx)Cs7M}$GA+rsH~}+VR6FuR?~&EDhHJhf9%<~AKgsfkvMvL&tor0>AsA%_Ok-K@yfp4_+&jp5p;c)l9lhs^zzUXx#kEQbQDxzAMj(%;GZLaS6klOg%p zjBT3D<6F~8QU7iehsxJThWbY>cL!n*G8VG$EWHYFj*U`)F3d?aynw$SbJ(fnNTAA6;2(gnAP`8^Eq}VPmzH2@btlM023pI!89h8vSl{U%Aj1+Yjr{2qV#U_>wR^ZsC*{ty zsm1<+`f077f;HW&!?*%GQ^Q1SSCo0)-LgN+!u9YIw;Jc1HY8NgW>lXQJESZ1_67aOpbQ7C zP5%k^Tfa$tvxCI9XWJ8dj-A2}S~3r_?>zj*_1Jws`;MPspIqp@_=#m=FLERQzEItn zD}i@eD#&EB-B76KV<{kw7F$JO{v$xz zjU>G7Y3hxan`cPO8?(>MZ(N}z>&fSSX5~jVD2Gy#lsL?HvTK>WYd2=Jm8|IGd)Hv&lVEu z-SZf?b@*4->RL*DQ1tPa!6K7PTLjv3kWs^IMwL91Y9k%Jnz%W-kjXe3ipOclcXd5b zrfgEO@y4#?r~Ac{y@{!vZujq_e^ALhIIOrgGjB}5+tDGt>hb>N?}$%1UoEzI%}rft zg5Q!nx+gCig_=D}^WI_d?p6FuyHpyIvTG$)VKEeboh{*bYB9WW*Yve`$@4Uo_t!yiY2F+q!+AOkm=ik*)7~;pY(%DFFl0Y}{s1 zbm>s6kfGquB9!bsNb0;;v*5SoC=I5_&!QhkU9(J6SgkeU5KW>a54Sxv3v4}G=jw;9 z)_M_>1}IA^=s)O02t847BjO}}s)kF@$j)neNywl6MyFbebY=9u^BfZQ>2CNenovSv4jdm4bM%+du9SZ~{Nky0hH220Ow0|olROd;LscxQ_cAIM)NPNNKlht0OeDSlnV%4J8q zzoaU-%G)+L#qq}*!ph*FCRT>UB#khIGgjAE_08uB=eleZyLDu9_X;`A<+E~TP^f*5 zVWQECw0HZCy2^(4N7Ll4<8M|g(IlE(VnwI9vylvJqu~=2j=m~CG%cT%zVQ)rg?P>M z4_N2p``%hbNF(la6*0&1UlJ!vq$~;Lj`1!QtY-F8SdCnp>Z=OIaV@#~?yT_9w74-} z4ZWhxaOALjgs=>x3V>k7CPmbsegWQNucV!8IJuOC#fFY=3S%UdLanES9M#N#gK)VaMMySADLJ ztII+-ZfO5Y@A2)9<9k2Mz8c=@pP!Y!Cc7G&SCbh@m8Bqw^tvA=Rq)cnLE+XfWdc>o zOb7i@##!HrHKtcqISdlN`xU<*u^Fo^l1D}mhEtKx(rK(v*pf~BesGKP{SYwAkk6cK zXoJl%(sc&7#AH{Zv#&WY&apovY9CXo?z>>xBKu@M|4dlsCCi>x-Unk@>BR^;qIZxX z5f2S&udPfr=&hf(+oif;{RW1OW;b#XEgw>?T(T!TUP=?x`I7kk+_*+W-YA@%Aq0PA z_|Hr{4a0N8H613Tril^Xy<<3HpXw~o%LTQH%*cvHeww{?eSo*1(1Cl6(5F?D*F`5u z^X64fx4u2}#H6+F*v*gRq6Yaw^D%~>@VD%ZP&E9FaoLJ@ko&agm#I#6>C(?EB%k^C z{QQg`qMonv=VB^ha602NDcOmFhL&YhDV=2wS(14pStk}HA`YgTwRVL`r5^@d6MKHF zm-jwg)~C}}YMu#5SVxY!9sI3CR0(9f#kym}c>;Hg-C@HFsi>c;Zf@-Fez5ke%N(PC zJ;n`Sk3oCwW1GXNJqFQY&{%)o;626p))Cr0^X@ zL>u3GF@fHxts~!n{ocr2wxJ_URYD|hXjgmSRU)7(5>IL$moC1y)E>+Iwj(jG_-u;b zOPat#=a(}1ltD_jO97tEM0C zleWoT^v9CiaiG_8_of{a6)5$6r{wqBB`6JBQRj3eLD?_~c(DZ4UbH+$&heLvv^P!9=z#HE%wBHGMd zg#KXI|AtSR*=%`w)8dD}^7#Vm6I3uxJ-M}q?@1t#54mTQx66A_>~Q@fT>x^r#xCc& zsW^KmIklxXkMKa{vmPKH!XaIqO-lZD?PaYhP zkVxj3nU6Z3vt+so#6z~DV!z+lx`2PfP+PVYqU1)(ca1^{U+e|U)oPf#CQ<1@+3(4( z+dq>SmDmXZL_sggy3jv<3_v|3`wuNJ-T74e#)iz*PQoOocb%#riZPnLq%9!qMO01Q zqu#UYaot=aL`_x+MtMt`oU@;_1+(a~{b(s?V#_2xl(ub`IYzL}4u;G3x!|1Rvsd6; z0L}>>Gs(tb=_#i4=lrPbx8*c$i(TL7T%A~ErS$)pDK+|}vDh7Jf+0NFl-pipOgPkB z7X4BxU~F$`gkV`$Wf|vF(4XD?kqz|DG^Ns6)E^~b^8#sO;AFt#a^hBc+#<2N{<+2d z4{t~6!OB~9m0xD%4B~5j5QUuROBlTk{{g_;2;R|s@o)LAv-{rWxlbzA(*$OOjt6>l z^KWk4Od*mC8-o^(|sVXpupii3o<4pZ_B<=_8NXn?E_pkq|=Gx6Ox>mTatRrYHvuo&) z{Uh&%%@J4P-hteQDOt@AgNW9dK|}dK5sI_h)2^Oxi}awI_r=dzqx2p(?DgKcr{}8r z;>>0zLF0>v=&Kkty`?G7HH_td}Am`quhzFj`l<*lNBw+cnp*4taQw#t9L zzS}ifvb%qBxLV?td5cl5)%0ZhL&*j4%-zB2zwJGD=8!K5Av0SJmmzrq0o3nDyU`_v4c4qQjLZs3&61xKnJmhMgIgEz=_eE zuNVx=fio|xK7$knBE%f2IP=3Gq7*d$S{*=g;Ed^?Gy^EcmZbqOOHc|3GvG={{X+@C zQ5!7GfK?g*KOM#*g&jOH*qT%WnXwVT;`?w&rzjyfj{KkaJ_xk`G*DQh0UWbQVWC1y zd;E(3s~*M*!TA|hr2zy*^#mJKKG0|Y|Em7sz;+EQ(Euc%B{9Hdt-xtG`D#j-j=>5I zn4XH+V^L=#AO3%!t`sDuioIA<49<=Xx+rup>H1Hl0dB|;D}+J$g7%*`0ZxI2F8D@_ zo017q!H6?}=D}ZZZ3u@G3nz=5hGDOz1mme*s!Bi?LJHVS2w*^5)wKVqR@mWF!d(Gl zkx7pYb^e4Ga~GSVm>4`-HMo?RT8HXsvAH%<&<33Y)d67!Q2SO9oEs@fl@@an3r;8- z1>n;)Fb3{O%t1Vn?dw|CC9b9X?|T~6wF380{|WZn90!uKbUM`To=@fun>G46f}Uv<>7w;O@+^7Ks^8qQxtqC zHwgz{{QpCCQw2dNpav4IS`F732d&iA_w(OLc5wYH&YoD1b&VP-%d{${GjKHu>R3;b;rMj5dQ5)TAW`R_&B_fr-s4^ znX!SWm4h$v0AeOb(-SctV^BlROl}x}lmdv^kpg_2KeApBb{+s1##DF#8WcuJ3CWN$ z!x%NF%|IO>XTW=w0zFL148bVQZ0;$n1e%(zQDVNk(>DI=0wZPcPf$So0AOwBD4AU` z2#R>KAdGE+NnkyP&7iM7j3j~ilvTwXq$h#uXqn-!^&lliLT=C*4p~054;`}-i~@nG zH^E@zV6Ij%SU>2ghXFfunh1dNiB1FXVSa)M zA4l)%z=*VX-RbPtkFbeBq}w!1DJSIgv0pp>a@PssSgR|0bM@>?v9jO_~yP@@^nXTco^&k@mr*+WHssf;2 zDM*z~1(QiyJ0SqX6#&)vK_zAws0GQI21_1}0S#iXCW7}B$7Qe;Vj*o11)yDEZgl)Z zhfQWmJOCUp%WFl88H3M@^>E)nhiNn4#7txXQVRwI^9{&hKoHajU|hi6I>Z4h2uwR# zeQey1y8%rCv#`tcnXOM3HtAXH95~v_|HB19GMCvfeWswv#IZ5JJPY`OX)1^TEJkWb!}4?uU}zRVF@+3z6T+N~cDuy<8M~TJ zxfbA+hT&R(-4SptFe6g)kO%mw4KoH7rRCKEyaHYcGBo}bW=Bj0RQWL(NHPDHfoTlO z10)krETCC0@c4)Jr&EXFSYVoSJ20PaZl}}=ssE)`fGrP0tpK@zsTG(pR68-l&@*@y z*PCm*qQQ=G9rOHdQl9^tK$u+tUe~h!ZI6yA+NT@R&<*VT)t8B5hXCpPW~xSmO|c2H zUHb~1;xw4{xZD)5n*xXmOR@m91CuPkaIniF(h2~Ha3ays-ptO}iNO5*0GARd2%38F zfBH9|mI28ETpOzg+%?R6HppskwuSYzMUWH2@4MC3h-#0RDj$JOClw1=0U&O90u2pB4md$T>Ik zPB^m@CYQc(z{}`#1YMn{<@AqA5%~gJ($tV#2S%;|#1B&`Fe)jCd(2+g7*5F(Qqa>m zMqUeP87Z;<7o{@1zu3$;{ldN=aP~&P-gy%Iy@bq|F5z+8WGxbFhD<6ALkIc$C&zM+ zJfJ$^!P<(OF{-B1O?$#$H|_-d^k$|bLqP&@%p9og?%RPAlc|peOi!{kPmZ?_x2I!` z^+HcJc)XK1Nm&bht-p-?`o0rgOxfMyl+eC6aO+#+1Hq6*GbU193+^1T?pyZlvJA!v z1`Q!X>(Xj&88uZQ!n{CPp*3b{ABQ!-XS9ZHSFbEIDDe1OKXvaXj?M&+&fz6gaNS>0 z^Y&Y)Ux$UgJ2l zwTVkZ!&iAb#C81y2PU>soFvb^Uv+J@Lw(+!l%|43GNoC~(!+;)14bKMkAvR|3EBc64Z6ASWwc*BH(C6F zz2t*HBzu0u-=7C%!2-Sc+{ne5onx0nN&^kI?KPtXnNsv%omAHl;wyaB+4R$Hol1&* z;fHTKj~x6Yv@8bi-2E!p9c&QgPRBOPJ@x5Rw|6r5LTRutLwodtF7!H!S?cU9-tHAU z6y=e;|A1WgwG(^uCxRO6kJL6C6Qs!1-4!;cE+i3;snBl-T!mgE!&zI z{sWzU!Olss*=2sjn{zVfwu6Z_wi&%Ob4LQ|*SEGe&RH4km_+-Jzm~Y<`Q-Ji<>==1 zX)P%S>KE0wvsTJ04CPW2yHp5v5RK+%8#%S*z1K@?{8J+C1OF9WyMn)E^Pf8J>-*NA zf=a^#j&j2;dbnC`cu0O()jKYIUpo4|XOvSidKiHsqwzPxEx03K$P(0gUQBxEljoX< z7!^kiu8NXJcUbvsq9V@sou^t9WbtYSJtpNt8FIdNZ$yWGVRx9e;cL@-GIZk|v1`_t z*`e#eqjTF75lp2Sgxk3&RLrC^v7gLgI%>#=n1gt4@>W9fg061W-G@HTiN4w_4D4^- z4%gZ}A~e#4OwSjdm6(!4nucBuJsZeidX&Lww5+rE`5RBx_GSQl7T;QvqjF;Ka=f1Z zd5Kg36=Sm0CqKH(`(CCc;-tmju%FR>mMq-k(rBqQ=FnUG#LuQ9Lbvz%Ofu z(s&m<@zL5PQNyx~mvwUU0hfMJ`;;k>otC_UVYh zQq5Sucg~je< z&qpObEB+Y#?8fxSIqmIbO6y44)Ss1ED3=Sg?|K)?^!EydD}(pmt^N{j>?;CYRS3l1qF!v z@6PfcwAE137GL&$u=s5@ZvXQbqPID!<4PUHS+!pggO@@*CZcfBV=``XgTK0ctdJCE z5+`bPzn}O>ZW`C;__LSV&9Y=%EGAm)MR6IUOQ)X8zeCEZNl|@nn!3Gfnb?x#uNogw zc_lTkBfm1t!((*w2_#&WH%w9eleanigVi76$2)#5>+Zo(R{oUVWw&j^!fBw-U8|9u z6F$83f=K2kb@D?7wr5P7u3G{^T`H}snp*qLq@4Byzd01z-yJWcEO=Q=(w03}1T~ya zygX3qH~7BaS^hZ9yX&ft;imdkc2Nh#U&tNpC7A~fR2*SQ#vKQNgBY#mZ?*>2Yd7=R z!>yxm&QR4)G7*SnUdxm9HT(N25^=+PlNIq=x2aU@s6uv|>{h)^FVA9C4!s*O@MSj3L?^tr@{%K2S#`ziEB$oAd#_CedQIEY(;?)WNi0@Aqz~Zk_Ia zq&80;UdF)vwpV2p`s#m_jI*XJyjt|{irC(L!o(>idb+D`7RmSf?7vAAmq0dJDP0Q}<&eRj`8Z0)vhr<*?uY)^IWvaa zG?F)#`-3hIEOB~YAQ3kw8q4YdocM7gpvpqNr_WtI{a!ZoKaXE=bhNGPl zH?iY&()>7&caREo(QAK&<23*6jmK%IXH||SJFI_MLbv*91Sp23YmAIcj(@4E9U*e5 z3D9}sMk`M~{c$w0w#6GiqxTaWD|yLWw7(X8rEh0u>SN8cNIZ*!yT%jksQ!HAkQd%G zM~?&a+X%)?qwhK16@Klt-FN68AXJ{|HSwK0Ll6Dd0Bulmh4)>JV$y7sw>~;S0X0c@ zX-KJ+@!=6!6bp+`d%Bkz#d<`t;hjIYp+f9b!a7$@jAwgYM;9EfnbPhp{OLR3EPqyd zLp2@EuHyA2-?{D8Jb_PAX&G&W-tqa*IxVd06vtIdqt_xxZh36y4zqDhl1Ej)i--5Z z&Y?FKZ@!58^Q>3x$$>AEXLjU;N}1os$N<7(Sdg*6fbiy;DB9(vjVCYn5VssnO$wtsBV8HU_y z)ueW8625kqza#W<`R)qWh0N`pVzHKwREo}G1|LZ@v<;58rL&@)kkVB(f(b+@A>Qe< zomDMi{CD3(?+ZO|F%W1@+LWaN!EmN5$$hc!r=x_Dr5I{R(}h(^pyx&rtk*?__j%Z|+;{qrr&x^UpQBE_ke;Yk!4X0P!C1a~kSM zzTI{F>6^3PeLHvQ_D;na-@X0vSyk5+eiVyl1?xkRaZi+H#!}Zh0Y2HN`pOnB3uP3g zQqmodtS={(Dag-mD?Oi7$4wr*p7s@M3ino>Nv1eNWL{;@?362dASWU1&fgb9DHRgm z$f+0o`gz~#*@JU~$mTO|+l!EWPvuJFRzD_;*nq!uf?P}0`lU3Zj%Bh2UUufx8h%F| zwbf22{bl$pw_KpdIYTa-yYQK=!FBb_Tl;Sjw+%_p6V|ogL;mcDIZ3*?GHGF9uJO}= zQjYxA*Ow;V>SoukdEi`p^XXOG7W=ZR+TzZ`GimH9>dO(vX06XY#FNJAB1@iIZ;fB? zo%W7;Gu#$=vC}mWy=(U+$WpJ!n3A8AQWE7OP!9pm*_MsoXJs94rou#BZ2uaF=1zN5 zM#gw8*c<#B@46!MYnbXcYjSz``M@yapUr{Z!b{_6Y%MG^EfQ6V!(LIlvmcroA4j72TI*Ry{-)TSS9r7_y{T-UqGEExw9sz3=|fpZ zHRZ3B9-J6zO8bL@Gqe^iffMhYWP&2qlB~@1(hw9xqE^kFw!i%LCX;0E%(m_hUOos- zd<}X3dCRY|+-jfuu@n{UNmRV?TxC#t1{GB2=0n}oQW@io62`atw#YMVm#{7*wIird zn=zLno>#fgi0%xNYU=m2pFFvk-a1g(e{AdcU5}^TB0Ep0cu+5dvHqg3*GMzFeOF*( z=i`>lu!5osdvU0c!M{dtqfjTyS57qZuYCS|D|z|AK|xVqSz{XY!hZLv>BjV`9T6($ z=1gYb3SYW=)m}1wm`$^P+Y_HR`p+VN>{Q6eBr)Kh+`=^kJ`*?O_@RhT((M*QZ~@Q2-3UWdO&$+D4W_Z!V5 z>y4x&&0=K`yfyh3dIy547tIvV^F|`XsCoXJh0k-*;_FkCKhLYkgdi_lJ@akbbN=%C z%cUf`i=~S?kFNh^bPJ~#^hWh3H8%Y?7(&~l2S=TJ3Locg8*8K<#9QZ+&9zN*1axY@ z{Cef9l1wyF@U)lz!3??+?R5KR>vv;{5O0O^eXkEBmg{M}rCQJ4vC{U>RLOSW`SA>u zw|wPInLR=~*(WN@KwEawuOjD)Z`rLsvhl>?9CL)(KE1E0>gu=KyN}V$?`;@ABvQ`v z3=i$;`1;uVWGgr#)@Xd~7_LV(MOfq-P01|nY)iqg9CL7VrdE7(N&%H0ubtI=;gy%? zQYtTtYIue!`QZ_LM- z125ng&yUU57VP)+%V>|F!=ikNIQO#TRtx#%2qZS_5^zud1)8 zE84}c4odIOJzl*qd+D{V|0K|5Cd=~KH1Mo$SI zdd;vgKce)(^&bhsjUF2)Z0NbRSMVfo(%H;_&E;0dAso+;aV@notB^7xPkJ)tTn zgV`?ES68d@Jm2X)*v)4)UaHT;Up$G5H-pwh>LGWWXt%5?+oii=VaD^xKtv zW=6>V&L z>vE4NkkqLW-T5PSs2!Ubawd&DT<*!tc+}&fFgkLvzr~3y*@tL$+vN!{k5}sUrP2cC z*B4y~_-g)CyIY&#l}&{7S`5)Md>-d6tmhPAE)C-RBTa9ceC(*%9Iwto)@uIyS$1;G z^YXqTOOBTH4i`d(=`#)8TB;!$^R?P2&T}-cNyx5jzVB*Y3VqmLc)=$5sDxbc%(rZU zI6coRigl$uj=G88w&du=a(p`RxXG(izpfc(nIG*7{CwAs@3z2I7(rGUEChRu$NE57a zmiUx%`|CjKHSUiZXnH*%h%$(UMm$_sni$Bq})plAJ2dCwAyhK`4{LfFtG_R-=IIdpN_-)l_zL>$1K*Qgxhrc6n#>AaP zQ>c4X2sO;~ORGPoJzI;$>|w*J@Ykph8?S9m8y>~sZk;6w8txM6EoRV-?d@Da7pEdMO%PnpmmK~&B5YNex3$_ z)lg#BvFwzGaXp4&^Ojk3yn@_2UuJbwMBadzW&g7`)&HP z4`OyPVKZT`jzgcJhL9tL&rjHSQEMS~ zM!I-u`7;77^RmV7*vxR*Wm4YWWRa<$At@1rTJvq9aC~@6EE5&|VnUNWQhb%N-D=Z> zw$-KHGFup|Rc3c7r}Uj)yQC}kg?_LRpHFiBv6Z6(W&9)L6KYpqZ}+~csoTY&8Kt*& zo+2%;lE16g&s)187@a+Xd$u(0d7Opb+~1oj?{(~Q>9n+*eT6J+f}iu=F!pUJoxdATC%NkhCe+swPKsV@&T+_E^C!3kY2(_=N6TBPB(XT7E=ULLyeqt#RUh=xIl0%>?)fW{w)0ayWEH}7B>$-lrOyZ1NkvVJXtIK`I{ff-Vc z;gR@zRuRqJ>!^<$_mZ3cGF^WB?wyWK9QxKxc^KfP+8R<=t*{hUj8cfRd`tJ zN7dC@5&OJReDv%6yq~ab3|qwHT7QZD-#7P!N>Sv5s}}hMGUOg}C8`2PP5V@YRy;bZ z+G7Qj6EXY&Ku4HJ^`Sug^(V6O*UD+mS}s(s$I2w5Yu42@A?L6g5&crFv^CH9^W4Ep8KcwbtjH>E#oC6HQt%| zz^bbSOAdl#cj}cb?@UOwuwRza4dTKHV+4O4%e&D?_1u82_DYhVw3-S^eWyJ)f7=Xv zoO;J`?)sdxL|HUli#lW6>jL{%7e*t>%XsjeCvjzDtCfxZs!CXMKG${>JN$BW3Q5Cp zd#B1u?4GQ8j-}!X((QTe=ME{8KEcFVbeB!FZlKpau4*})=RCWNvhQw16R_KDpW_f> zgS-Ycgo{f=wnx@+Y*6R_xJBMpelR^)=T|Cc{=ylU$GHAt+$KfGyI&5kzgDLC)>q4=L-YMP_y5hc0yZO>XYrw zKjkj;`wd@|r5>ka95P1FzR=FWaVGWR(bE<4&*wW{^W| zk0MM6el<0HFt#@#XKK)pi%*YHc#HZd%Pw?cgZ#VitBl{s9wmzNG-~PKW!ej&Z;l#w zE>EJ#zF3{LS@XclsLQSt85_Qxs7FY&7Eq{m$;6&3*O$hU#k*B9pmuFz|Lwb-Dxto| ze&ij`ip=>xp5JaBIWR5%9hu-jt<+j&@#&RBTSm~2I6Xth%MZ>r4##_Stvco9Kq7W@ z2*kcl<4Jm(R)s-$%wzPgx+A>top1t5S}*AQuF4ES`wzs_l487jVFG#G{o9(=AJc!l7>-EeBN zoGLy@L*mcmVYW!O4@Lq3{7Czs9Si6d7>B^Uja~kqXTjznm~h5&Fw_)qTZjUt;}k^< ztp=R+#@dERL)|SH+Yp(5wjtno`WVdv8R*nE1cZzcsE~nR-w-&wu?|H*6_SB)@lKzk z#&{YM{skE^h_gx&s1tyWuu>J^zIU9kRE0EFssfCK7Iiw7|CB25F92^GSSkW;Sl@w( z30%SIL`Y+lD&Sve^J%dogQY6qaX+Qvfmt}x5TIuKV8i` z1;8to2_+5T9%Cp?AfZ620{n=3`!p!rKwU6AX{ez5-|#Rh6(BAk(1FeCYYjlLlKxMj zgEsKL?1Q_2Fb5nOZW2Hy;fH~~Rc~M@T_DVSR+v5|4Zv9-aRH^s(;@x~=v0>jRV>p4c-0i-VJ)F3W*771& zK^s8IASc-h_OJ#&8QNo%Srl{fe=`##^c2-qeE}kMSW^H;pFxNg%ow5oZkLug2!w%VbwCT4$$;BodJK3fEFuB&vcYVRJfa>(&lymVXK)4- z^!wD6M;wZsV55ZQe==hZ)pM##IG}wtn9T_>v3r~*@4u6upi#jzHUiAKPt`kI)Xd;IKIml`dpp_4p8(_+fG~}D9`QKUJ$ayVTB*52?2PSTT z->x75%CF2s`51w~1QU4zXlb(*>=ca+h$0fqJzKjB|FzGzkbo&8pqi6UPt{ujqadIY z0$T=2%RrH27u?W{aLJoF;5mW`Ujr@LLm_an5SS&wy?FG9>Ig9T!4sV|COjI3kB#)=sY!~ z$BMx4cW9j?fbM`X;2~A`31>hkJuXJ*uMi0lI*ko+3BwA@cawmRw?j{(crZna=?^xj zfm3}C%(tqPDmBD#79jxN<;zL{^g13(mq2at$}~^}>I?z&caDt^ZOehs$JQY3p)gGI z0Xtj>_6Rau1KtwYIdfzN$_~J_h7ua(LI`1QE07{OUBj;D5LyIq2Ecv}jFsR;yOoO} zID$F*sDRl@A|J71>v)160Tb20?%)hem0&3ow1)tq02@OJg74o6ZO|EQhX71(0TF${ zcGArNxFtdpz&J)i7=hX4P4~fKa0rtkM-K}l>M&bTN{Y&Vv$pkw2Sa!B$;Q+kc%Pln ziorfA+CsK-j=xfVbDG9w3Z?|E?(jvKDwPQk{pnkl;l}OA0pB zjT048$h(1z7)pv`;>WZwy$*~yE=wVV;7tKE)Wc|V$Ut-JGH?}wmRKVt;OoM89`s+tCQ8f?U3n{$0Bz>*(xM3z5##Vml7VOu7#k%SD5VNxg9BdM*n$Rq zf`S%H*WjgqPBalPhfW3>`$Yh@nO2v4INjesfwGDe}OdX4MJ-Gp9g&!0`*yL$Wo( z3w~9CiDUjxRtD@j!dx&158MbWzu=(3A39_Ru!zz8RFHrJ0$UZ1aYSy=*97`3s7pYO z1@du3WWbA2d{q`(p_uStwk)PA*z*e)JVzQ7hz~oG8j`qf>duy(ZJ#~ zq-Ya2gcdf%rw(9X3Z3{dMGH99822yGog|oNAW#FpL%~ygiv--Dr)i|zkm`NnK!|FS z4+#-@AXYJf!Ma@&LLP$Qi@Rvx9Fh{0%i;>sVbBnEae~MH> zJd5ofZ`ftIq`b1B!1b)M^_-AUl}mDUPl97>RcixR=dCc>t$xz9f)^K1Jh7|a4^mB~ z`SWsy1+|Nm{~Yh`*uO^^X~!b2#aP%izfdSLlwM;%Mc5PfqVkk;?K+O%lqdaF+S+1x z<|l4FGOs*peAYPM_Q8znm4)fA)=4V?5~PMY!jHJsQUY-9?lJau?#5NFsu4;ON0+I8k*kreZuO8(d@H-z zm2+MTj35GG@p9LQZKCL#`MJqCo6%Yh{1b@yh75x58Ity=^}@C$?auA zmV>q*t_tU?AL0GoZoi_(%|e;cbMWf;9Z#-z?iNox1`{GE-gYVNre0NMGywNFAj~8z5?@7M4I*yGbvOZgf z{^358+S!RBId+)kL0Oaz+LP>M*U6g)jmLg7erx`zH|vGpq}*4p^DJisp5XK3jZK;} z(7kUN;y+QO@30#TE>>HATbDLcMt^iWutdln7zq2-h9CR!CTF`Jx-{+YO22UZjzrm2 zG~9ad^6uLA-8J^4*pPkB8FZ_G%G&K~MOVeF87%fDQQy3Sdvk&kJ{OuJZ@ktcn^jFE z{llwqO>&9t(%w+Jrb^3m&Gd~pl2YNeJ50UPJ+ljoC&-<>A4u2PquSg6Jo4bo#{KWb zT`!TS1L1hrf?zbNLG8Sxr1XO43rXeFnLWypWu@FQ>nHQ;X0n>Q2k#CeHpEv5yxtJY z%-{J)dJ&alw;eX+l5U#kW+k#eRT;ZT(m#2SrK^1tde`%;?ejf@{p48F6%HW>8r)6)_7{-4(-Et?cU}txs#}ROk+# zN?OoRt+7gu&G{X^bPQ{hl(N7%ZsVP*R=;XkG;;lJa!yl**Y$oGTbd7Pam4)MPFl6H zl8>W0P)}a789SA;t5igy?!J3o@mBGTn|DeO!7CA|u;V|MhzCg<{H=!(@)f=*J(`i( z`7Jqn4>;slIpoUjYUD`Bb080nGbhrQ3`S{8bE1eYDx~i}56ht+>TE9$$qD7U$dV&g zQLHh)_h6qz*xr~=^-8T9Yf=1ry2>NjRLQG$1mq~^47-K9jf>sIjMes|qa^}-hzBJk zZ(R@hg$u173E@;$7QU%K68gN?W$Aw6Q+c-`OH8R|($M?TAai}MfMrQ$#FvfCwWsZ< ziz>HmE~yBWgMZHrF15#o^8IIncvjDS7`N{7T@-!Wm#XKY($P}mxEfFUw*33TweCHO#4ICA|Eh@9c&%H$W|khjvi{}a^CpI0W)GSp z8O-+@-B~zIN>*02Nc}m2!+4$8T z^FGcLgerpy zsW-Bx&TQPadiWr?gVrlx{F5hTB4tRM9cx~RXC}^P*;tJZS%D(bN6sEkLPAguS~sO1 zW|ghz^{)h2^31sBsap}f$K8`*6OXH7y*0qf*^63ty)Al^lBr_E>td-jhjZVBG<@NIuc`c1d*xzdN*^ha(!rO&l_Bi@cL`)k!v)`4~?M+dh;>RH89Q)IyC z$DJ`0=}7P)V^htU+t*(GtQq01%9raB{3sB+g{bnNCo^nFpM0BX!h&x986D&|-eY=k zw<7ov>Jd7%jC7a7L4x#)YU$YrE`MHrFKvG{f4j+;WroctSAS$@ItI~n-RU9omvZZc z+`5C*FS?Xb^((TGluBQRM(_y|KZmEBuN`}+lzHq~Vq7|S$A4?h;IYx!hbrR6jEaUU zB|g_ISb}KX)`5-K#kDu^g(!w#i)lN)5jMww!Zbs9?oz6Sg~hru z^9GO$y~ukleyI}iFBfYlO6-_27pPA{%rgEwh^oynk%)S_u=JhnY?SqD;p=9mlCo0Y ziKyI72r5*o#7M2xl$5H83^y#VyJk*MTjpeneeq{=j-+0F=C^uLDnRk(a<}$;<@x@i z;TY8D4Gl--JD%r0d#voRHJ)p5?#F)?F!^xub$L|eym8&Y#SU(nEHWq;Lo&#pQpaKyX_@L}_Cpp=44gH>?1RQ>p@(Qx zircv%q9|5G`%M#HV!=1A<*L`Y>L>2k_Z3r8-lw!sn4-$cDQz<~433&6k4|$Tf|O7u zQa`zhDV|oZI^FrUaxGJW_IB>nSC2&5cyHqP%~r#E&s8eK)Z~AQk^8^*@W=y{>^Ih(ujDCyC!Ps38&F+xtGcoK=D?{l09{aP-)j1O&g1!@ z@XDmA47qlS^ylD<5`I;C3-}MdZLR&#PUr2N)!j#bPOKgg?iq8q9V(?~?iEBvZhh)X`hL@skYMp|#F0IIrOKx} z_$Gh2b8sx}=vU0t3Vq)pO$PTz3M>dq+*`A4@EkSDK5g#ykw{j2OXEUR$UFnu0 z%Im{U+O5d^Z&!cK~DP2<@|AV z#cR}bhoczJ#>|Vq;oiz^M4RXi&yua?*DQl%f+Lb%bncm>+5u5s!L-`ewe?TV3#3Wi zduUESt*Uj>u_)Ew`bw(l`Il9e8sU)h^}^^*7Tf)j>N6uPy-)YwLsWtmoIJx7zc-Gd zjD|~Rtt{DG{qM{^e~v<2ch*I4^(& zk`3p%Z3)k-P6bbrN?zOypA(%)O1<#AQjC&BV#WUMVA9;L!Mx4u0)dCl^@}5e&N|~a zd6v@W-z66Z5@fXD9S+u1w@@NzaYn9a$THF@`nDuaj7EI2(MW>^3spK7QojKUq^2ct zX_QuTxy&;6JvK;b!(g>~!`rf_W-{)VF7>pmRH_+^o{_4PJ)rerCRp3G4f}cMr)4i%K1SPA7XJga z=D(4vh!T(WRK62e(sTbO!M!lfOU1pPc0YWYEIt1VhlbAG6}hs>O%^uvOD&|~a@P3{ zj(w?UHX?0n|P#$Jo~Nj0E2Bk+~TE-r`@A2sZZ^pwI$sXi3~*|wc$m$p2WGD zmm-_?Y$3g91ShJIDEKg93{eh|~H zb38V7_1vbOnu?^g)4&%diqDN%;hAwrA=()2!dG`?(2jdJeXr?xyeUKPxs%9dM*ZX5 z8iB7oub$J};Kuli7P(9GYR{;A(IODN&3$J_;Un3BXU3}!YTonvNBtx1cX$pSXZu?i zsaAbd%@oKZ*MD^`gVeeiM{7=XK^wimQF$+T!8pp|OkP|a+1?FVZu0^8dl7G0DkWVZ z;TXhOTph?D2Ei{ttsNeLOz@q(U~9s1?^Efo`uN>3US4J5A9w8^3fgB~cFvQuB+Nju z@IpB;2zH`ai?4$5MNoGPLfF_mFj_*DJYIpX>YggcIa%_2qrhr?z2jCeccjluz3_~C z7FQvI8OTOqj{NkJO@a(9g7f^`%x9ImeJ`?L&ELLB zU4+-~Z9*2l9JNpGs))GMnXGQoSDGdQ!TD76>eN*lK~A`Z74%K34Cln}kddFMMcB<> zNRWMHM!I5EJjGTo9@qRplDtHocOcySfzV@>RvX?csS4PvCuatf_+|Xz+UL&flLh z9@QLAoM_*0G>!& zVUZ?o12n_gdab$Gbp0Cck|^y^rOoAf8k!QW)U14)cAQxwv#R+JCyEf)daXVwnZhhH zkwLOOu_q?+<3bX6%ePoQ6kjG>^da~7K$LCbBU<01y2{1VL%q?rWVif~(Q=J_oL9T| z2}HRuZ$?pM5H9k8fllra_bgG;a}?R*mw$gMT3ELW6Ff?Ixs?9q`A;{>`P|AyrgmC6 zOVJK*&o?2V^xqyXX>tl(N%hAOjCX!tv+$k!f-A|)Y=Uc52(QeOnr9hFG>%LN?*fg# z6CcN8?}*)TE&vN9Td!*1#R$W!utfB`^WS|B#&{DLu6*u~UZ5tRd83v3;Y?Q{>IR3P z;D+`#Q`=qhn^_EIqm}E|Rm;^s8C1XNVa+jFEI8MSuzde zfFMe_w!VU}Y>4mfRWhY3TO`}}8Qq#Ii%XMOoD{C+KG%znEaBAv#_w z7SU9Ec=u8@QMWHmS;ek@zPw3v;()=2?1M0sV5YOz7@w*X&6X7@?Alwb@P%{q-?gLs z+T{`>`}ilV201bYQPvJ*Z9E-aqd(!T-XG!_pE7H_4QUUuE9=ed4;-x!ycEx|7Rrf~ z{J1Vdv-Bh8Q1@Gq^rHbeoV8N+@yRb^Ut{xfVUiL%ASsOi+Y^Y?*ywKxS%7(D>5RwI z=p?+774jd@@F4qT)TUaruSJ4l6w8?s#4yrcNQ9~*kQ}F{!krw$D2fk^<@e#A5YbXU zqfLn;yWFZNi{xBedub4Q-cm^RDE%_@8{xWxp&g$XB%+2J}UfXISh#{XH2U9^3Xo#{G%J3 zIU{{9MI^OkPL?&}DL+oNGMLE+HVo1eSeOXZ}q|ZX8ZT_1)I9xZBsY-vhNd)=-u(hUUy!BLB z`Xhmuy_6+dQ(GVmCCEt z-0mZtdA}n*cGGMvuklLSz=G?oJ!mEgfeI)U_CP|U=wb(nVu)2a4R(y zcY7hwzqh1VUqYF&`zlH(y$Rw>MsVwO@GyKx_|rNZ{QGYe%n920(4X|;`PT-bKRatl zNzV<^D2dKLe)0Qc%bdwS{P^g8lC@IM;F8dzP5Y$3e{TQ&P?v-vK;Wd;^QN3~f@FYT z^r^!OfMCj`cp;w_5n3qus~{zGG)uFL1t73K9I_Ct?Wuar2@k9bBMYVEV>lcDS_D2E zm@C~`N`Pqt5K3YZED;ERQ(NlD|M(;+SxAhu%ov^=_8PQ#fgV=D0kB9821x<<^EM;Q z3;}RU*{K~29(Wc> zMZv!y3l8@`gP?sRR1b8ekyTG!d0GlgE6R?D2{}G}g@jzi#`B0nY$XIcOl$BaFTfsK0RqAQvO2Nr}#=Kp2o0l z`0L6*$OjA%<^lX|K)_n_pbTINz*9dX8wqJsk{&3;+T=VZef= zFc|>Uf$4RM3y_zk3<*SoM!@PZ02UPFcSBdA5ock+`fdqOJ1|`WfOm4x*7H+*6w3kt zU?j`}7?$UvfHpf$Veb?I##3TWTqmLhi`S0bmB1jzAbnVb6)-`vd0-S0Odm`GxY~;W zdu5@>CN2hH1u7>2t5vxeaTfd8&3oQn6z{^J6GIW~nrE`VEv47N+a0D$Zg z&NQN3hY<%bq6*q!X#imTlXAg{1dXtWDkyY70|46lR8Z^~2A>66f+Q)1*HZ+wALFw^ zJ?qS@(E2!H8q*WZ0)PuTxe8-KAd4jdz@;vR1i1CW`_rLd@PC>ZE^>7I1fm_*o&m$d z;{Tux7XJt95sUwWD;WHr`WY`3n)5Ky4 z0iYe05CBqzB?Q1dbua*g_$LNy2LD^&A?t=V-#{o~TSj7e0J6X^N>&x{06=arJOFS( zTpuY5sp^~~gj)8n%!;uy)WCkDk60dUvX3x^sZwJ4^su7^D20C<0Jw|#vlt;AFb6OR z07Jxi^Xp$a022UGjaF_(Qyw91VCVHeDgY?v$Rgw^X)L`M3Cl8pNVYmadC?fMP(pdX zPrJcT0epglv(UqT5N_CR9NA?t*^__@lC?2o!B7A|T44&n$UYkd>?;9Jdt?<7LuhE+ zN7iEVP#}T<$U)-%ga2i*@IUmzjvly}&;a(&FfkIQImyD;hnVr7g8g7- zocOT-JJ`3dfIk@2Yy%SG&_NB!lOthr6ZmP1f&B&=xO1?N8fcZf}O?~KrmjEzv zfku7k)!5!ePHneGYw>c#e;~d8+2QV23W5MGm$|#Y{+KJZ7{SC&zvtU8D?Pt69mBagReM} z12zbtPr&3b(1Gt1kfk~+&cg%cTM^%c#DsVR&_idDme?8CGRKf>01?YvA4u|m`{A83 z9R(5yY<;L8eJ&(SRsthv1v?!q%LPTm3uZu@ENl#r!@e>#I_De`L!SV9tl}wU4T^}O z568ADQ&I&hf?fi%(#d&GJLBvDokgevE}%*$YbC^fq+9{*@gXl_+H8G+?Xkc<6OGw> z!AlqGSpvtPA_iR+K*9_aP_q@RZs=nHBoZb}fF->Fa~;6lr`sjCK}Qz5*{Q{XjEIUL zWkH@%iS!Psn_HylF%cv&HV3qU%9sZhX#MB$0v3X+K44maN@NDIbUrN`}mUl>)j}@?Bzb zbb>t6nFKDEf{#cHkIkf?JPh<`nsr(ToIYHbH9!V2Xr7kQ7#EN;!jw^+CNdqv>roTC z_#fHJaT>c4;V2_>up!{KfIZp)Yz&wr(LMsTKKd1p99ohk;D$D}S=>+S$^iKc6U+h< zcADAD!xW`=KD`?FzxsSo4(>*$d5TF)|)I0V(fckugw7h76~4 z99i(H!ctIiajC=s6O;;CHa{%^wJd&nh~^=`2-NlHTp*Ok$xDakw?yt?r$mif37$;w zg2i~0fa$=63ArHo(oAyD(*ijn=%N*NX+z>%cy8#=R>&%NdsC@8oe$iHT>rhXB5g35 zYhYgHKmmO97yg#JIqzA`MTF8-E~?(XjH z?oMftkVZnfo1vt;hLSFkM!Jl1`(vZXVCZl?|q*8;eMJq=j{5$-upZ=Yp-Sh zTZXXZ_iG~Ue+JeO~y0gm}$L_d}I#$bB?xU==!MwFusIK2Anf;Mk=xA6u3krD5Qnw+3O zW9_-lZ>BV(!YrfWu|lzXc*q7-oVwKuv(7Ad7x@g2PtKLSu?%bwIFHDOrnpI$Eg@MJ zPvvR#?9UhN!a>`EqRlG>mWrQ!Il`3th>gxpgK@XDjE@R!apA#W5+)He&<d!?*h`;x>%^!tFyzqHp0yu2t_5{PMpCF)f+Yg$*BQxlG_5>46@1fAaRupcr$g$F)B3ye$K zd!mAx3x|wu8Q7+_7nQXJ@tSE$9VAL0zYN5plx`28%-Fmdt3pYP_;b$N_M1hmrhM)^ zfaDNLujoCuSpb&FoKg-HdO-QeDjpeF7NNI|Gv%2Jk7f2sP-&Rb%`@b6PU< z;pgQ&Gxe;K?AzRk6~rjTz~Fm;>Rdkm2kz)wicC27+;n!f1ylK`&5V~VZJ}f>np>Y* z(zA1muKd)DhjWb+b&_o|(woN?I*-UK-IesW&prTeH}=Y)Gg`|+WPZauihFKu zeKUX}utw%lj{1l9p*AU=AFf!il-Jg(Pl@#5+RXK)l+9)N;SsytGtgaKNtyRih8*q6!C? zF#{)bv|lUUaUs(t&&=nT%nkiS=GcD&#q<7?Pz%)yhPg;DNo7jGkFz|8>aS&Oc?Qsm+f$a_S3^PF;45w1JR2t7ma+jySI7>xcmWD zs(70{PH1q~YBJ=lr7x#p%h#h;2A8`!e$KvdDdZT#UQ ziAYqJ_d*N}s&S{)eB`Z6)mVXGoS*8#mPw>XP=3*Ys1U7IWSxfhAFPCIL zo67|;SLeb=1u2l651yaKHoKEQ5E-w>j7`JV4;6zW7^}pGKeoW~zBussbaHlF@ZfaTnfwYM$d3k8qKM9HK6BaIc1zscPOQ8*+SENaeV4 z{p}+5yP|-C#AyQu)hT2 z!DJIfJH2m2l>)l1K41S_dESHZcvMHOf_FwyKsv3WA)mWgSQG_cho@V6u?Y{ z@^lAs_dw}V>U0K}CDA}dsWxe-SZ=oA)w0u<(kYK3V)6_OAb&qiXZ~!A6(lk64pvtG zT{G0p3oy>lj}aeG<4a$K5PCT)k8@l3)CiQ)j!vXWuQ`=XwMmQW$#?XPwye14<#K;* zN(Y^_wta&7>bS!y#s<}pJ!UnDd7v)4KI^B}$g;B9;X1<{^7EW%nw2^Vx5f_Xn_-&9 z7gmefl9AV6_&+z*+Otq3Ceb-!Fw*A*87 z=?juAiqFN3@~n1q;J^)SeOkIX5F1Y7ZJpTzU`XB#Rt9QXMpL2;Xp2|lRBw?7t6m`) zC^)vbk#`cmcl25k3jz;`$1y8s$; zF9=u2z7L72L4V5bXpg+y*1vC0bNpEkkjj6LTR!b;KaG|RF0WUj>2+41Av2hHGsX&FJ)3Qd3?%ar*tg4ktaApF?NVQW@nqxdMc25 z14`VR@fQ+WdA&S5n%a_roUws?LK(*dgNv=EBI8k zz#c^J3vKq0!N#w!_?~|Kg<9Oq?fzutXtu=U$Rgx>ccMn+rS=viJ_hxx&;`%0HxtuoEe6_N`*WU^213wmiz>Kv7+9+-#2oN2rw^ckO6~ zSFT(!3kNs5e5X$cjO5C^?Ckat-T4h~SF14$hszCG)2x8qVW>)exJ$!rClbH)^7(xs6J6NPU%_cINqZ zGbC135}Wwmznz!zlRhCD=?s2AH>~1Wg|Bk2!5(4O=G5cEl&hW=c~QAoVxH9$jE@!4 z8@T*4>LDvqeKOb!YQ)_Fy4k4|f)Z=nYNuOk1g4d=;^}0neco`l9Jfz;An_?=?)#0P zbhqQFv$kKZJK1iluY!c-V*|C0Ueh$?F-7bV{mPtsda<`3_)YF(e0-@*6p8EIwv@BT zXN#T<_0NmdU!dP&XblD(Al$i^HI{v7wJ~;SY;^iHhV$N28S;;&IEDE4zPqQTpiudsaE3{vY4E8W4_mc+VH2szryy>xxY&;_J z?!Bk4%n*&u`I@R$#_o0&I6`TZx|sA-y&|~tGzTle67$e=X5;nZ>WW`9dlaAq^;dD< z-{1Sce95Ar&Bp8y5xho$_g$;7^3D%b#TvDUt#DpK88(dt7ZU${gQXor=aRxp_pt^G zm7Z}ZEVJFZpbeAcy^K6-{3QR!D$4|)22zFYPLqbzoE16+#H-6B6xk)aS5$UrspH>& zcxvlQx4?QwNHk)hpEh}FX6oX6=GM2Lr$p|2TZx2PAqyAV-|&_W6{mP*=umy-RiGoa zJ#HoUEGwtQR1cjgW*=rU2*%{G2K|du6UGnfAvcC&Jp$P6DbS`rl%;thT2QT$KMCD& z_)$~A7kW7Cm>)Z~@N^Q__?iU=&`y36G`4}VvTm2gl9L4yJO=~&DfIILUa>9=2xjT? zLo%^WaMZl6bE=*6295Bs>wd7y_!)LP zh)`Iv6vmPRWX?=r=?LWKzJesQzcvpfNVv@6+5q)X3*&rJ|08DW$sfBr?UC-#efFP>w}u*R8i=H-W&m6qP2W5OL!tiBwiF&HNf72j>Wu!Nasmlg4RdRg{qp#2Nm&>E z^4@49Gpp!wo78mBBPK6q3`q13jQLy1Sy*A254L+M%@rVw+$$mIsy)Z_){%3(>u}R4 z^51d_uJWf&t&Jczg~@qOw{-cP*0qfvG3#-jim=CFF(|^gAkEIt=p~y4hB8A0!RfOi zh+ou*zRruNq;L2!wAxe&bab&8m9Pp23HCXbcN&wVu;s4^+lXC`iENp$ar{OaSyS`* z#WtCL*V5i_X3sKaz{HQPC2uqs$Xlg)Y2|40!vuxl>RDJv}kW8GUljPjYZxN-YU*nIrXvx(Sh<7%1M})?zW=s31F3$KNza{?{6DH(vwHn*;&D ztmX{x3~dZu^i!o0uDJqFD56wY9c@`?(D1d_2l7v~^KISQq|RFQij~r{@{F>ci!`?WIE&#VB1P@NfL5$2Bu11;C2QzoABct4vu)95u>KhR6h_s6(c zTfnNGyCJ6zAf9-DI&>nJD-YkUuxsuY*#}n|&Vu3&$}i&8i_?7;*)A%IENQ(Pm6E*s zyU227I^pVE%L7AE>Igu+p?+7_Dnl@8#h-mBXLwoR=c9$SHeX1(RHPxnk}in2!`676 zUSBVPYW{2)1Y=Gqc8AJ*i2bY}FGbFH2a_7JDF})hmtBVG{==(O@0e?rG8Crrxc4rk z5((r;6`Z++(~K#ez4t*zpET6Z7dF?I%=LBVM9}LXdnek{Xo|cE?~XXwP%{*t5Chqe zm-GNmuJH&Q)o6a*xGDUl)lA^W`X8~*((<=-B6MHpNPkwRI@3W_k~1NV#VU`uz&~73 z9QJ5eA`u{$P&aC1yIHZ>)TTl)RKbS&Tz7yhqJO!L9izP~S|I23qVD)ItoXYXW49|U z(&|?P<*f-VLj07|72YP-{?Mpm$I`Gu-dd~2vP~Zi%?+%n7Y(@ii+G1R^PoZDY!n;Q zwm1(ax(KHmaaCEJV8K9g8qHg+U`a*Z&1spzHwn>*LZ?B!pV6h&?-d#dRng@MDQ;jv zWaE?rxnxa)xPs0qi$4cH8C zmlXV6Yd@(X+b|q=kSGRYYSdMa^sdSJLo; z9$R}`UM0MCh=q?U@lN~BpJi}wy{C0dIY4f}pAy~ayf;kw>IG?f*VkXz=p%TP^U*2g zzlS$}w;pqW{;(+K``G-zF6DfWSXbB@&A7Iq?&)I+jgh175FwJ-i{c&gZN{ovn`A`|2Ic=BZwenum8@Ma+nHDkS3*SK z4?oKb`Yin0nQZ`8Zcxj|L+g2Ii{8P0S$#VE?PlSbZ?70Sst!TAmf5F;Hv7RrcV+07 z@kOXVs7aTj`4~e(G?zEcYN4CPoroVyQg_{U^>JzzU`Umj4{Q~s3DX|tjC|B)VOM1q zI7-E+k%?66kcNpS{OG$1e9M(Q>(`1b?B}LsJmt$;JUipsF+mwrk;Z&=Fy+|*A$NNg z;-1yziB?xqi3Dv7x4Yy zOBgFL=iBxBu5>|&L2b*Bz>XL`6?r)8hoW4oUA6Pv3Vwt(?vX+SOWp@zvX<}rV>vJi zu;DUOV~Mf2-Jmp4y#OEnjT0>*BMZTlHy=hZotOJRT&r9R1bFjYM8sza$-YR;HU7BO zR=ungUD)(=CG!2xTqN4dc0tO;p7^^?2Q6*p7 zuG?Wfl2j|J>?uIBF-1kY+8fGZUpPgD)eG+5PW(FYTKfaKdo;}#ICCZuM-RoNoD$mo zns!HCz)q1A{XRM~V1k@??WWe>)ITK2qysw2F@NVtY=~p`ybP-KyJe7^M3h$m!^|E= zvv*l9xAnMXNR!KisP9Xitf9H;GsD$s5Z^k_pbewiU28NiFJ?&w^-pxk1lVp)+q0)f z=RX0jT6`8kL_$+s_;*c&W1veNn!__yYX|#<|;#y5+EJq!tt1o)|rrHNE>N`>#Q>mmIGPPSq$kCwn&bYtS0o3ug`x zy{i4|?KkgQulRmv+$Wp-c49fM1AhGFZEE!KIEBC1ul%|T7|RDf-p*GFIIuf!d#LEyAEb*ZIQffQ264Tr zSq?1K8ak-g#g@Dyy4)`upX!Cn_E)n}a^3TAV9ZEC5&;wF>pHaF2jk%`K4tgHK982- zwST^T1wHtbE_olHa^e3p!MU)@9?9?LzQ-DV!N6|#F;vR)fIGw%dL2iC3}IsO%d*a3adH5tt`LfOt2UO^Y%t?V*R4q1D<6?M($iE(Ge3fP>-dw?xRsLTZNb)1yAUK zE8@DRvnj&HEW=c}nCK7jpiYu_{TH~BG$;$XOz`O8sbI0K62p8jT7w`FQKTuR7?&in zh|GqCt9Q7SBwLb%aPc-tI~rJ`L68)5-51PWuxedMRj^$;_4;#$XW>wouMJ|2FB6R& zRk@^A6BI0_+1|$BWEkB9d~N$DcS3Flj&%pKZqh7+;X*4vX%SAkueG}v^G^)JkM|BS~6Dsu``EO_f^j5 z3r<-b%J(mYiaIU?9R3le=Nu+>0uz$Vj)qN)@`3Ir%LET0vQpREY6f$!N5`aa3}X6T`(#N&Gk+q2B)D5aCQ7O}c%_$ApW&;FG-P3Nm?x~sbG+yy^9 zPoal5qU(71(_rQSd+h6zuy%AX(grRy2%l%*X7{tb&^M_>%5r47qkYEnpU$?<%JheA zYbu&Btra&KHL?_1oC3O%`*djrvDF##pdlQa#k?kiuh4c~(9(`A#~FrN}(BTqW;*+H=ujp}3UxRxU_y})bLX^!A-`<^k0+Jw1{9jCm%)#IshmyBRM z4s&%g^iSf`u<@LE--#-*1=%o1Nt5)t8Kn#XECrI~2GvIFrv;fxIu_MnFoWXe&wDwz z=g9dsUXz@1`+J2%!fo#s8OguUKuM-^PWiri&ueEq(-RYijL;h`y;ZVQ4C65Xfj6&z zX!w9;IcP7%PFCI3OmR8ZS+G@;l6}yUG_Q1RRZ{zUIBJCJju9~|Hch4{jkA7{DzB~N zH@Z2_(_@fQGaZlfAP_vgzE8EX|x zU!#e^7e(b#^Ua6ZVKlcPD}|dQNL4A()M_%Mk(r2945&-i$K~2uAYg1?uzqjQx6JZh znV<6_h+)-Sl_Logd%29-Nrm>$4>Be^{WdyXL1}4Y*>}9jhH-PRcdpw>Lh8!btKK(% zdC7Ck75@8oX5fz>p2%u%$Rv--NN47`lQ(h{5Ykwn*D%1Mp8O=Bb`jhHrKClvsY0~$ z2t<#HWM%|Pcct&+GNfV_wwM%UF2p<_t@F`}7%)6DAJGY+_iCY+`rdJW)nmLvQ}zh|oXYof+N%Ha8x9n2F7a1b zJ9M8*IvX)LT*0)rATV_ydNDjyuKz~aH@Tq#4hH~M?Z3+x-ZeQQ!Z7^v6={bnLdQEh zkJIZXos%-IHgcK{+77eeZuq5-&TG6;nOl4wjqq^%Uk(qi zFJ9ewXi$^rghY|v$%(?EMfpsQNiG}(lL%K0Gk_?wb}2u(fu{6dx9~f`zld5tM8hYR z7VXQ3MmQp7uD%~yRSTaknZCx;kL9ZWF30$}6RLowkfV5iaDn#xTvH5YX3EvhP^>?~ z$RQOt$ZO00eH!K$Y23<3(>E_!+Mg=WFh|4(oRjj8q73Wfw$vW7Rg=9?4n*N$JCbnu ze}nOMRvA-IK7#5PiJDHnx}=2KZNkd|pzE+^JS7#lZ5ad@3k(S8`k<_C&X-l!D!D&n z>YDESWA02VTB6Fl^skKwr?(=^h^^32J}GNqt8+^I2}5RCsp(gh~3hf1vLt?Lx!DeP&g1=o7vQZA=$4y(A|_Qh@rDBDKv%SHJ?Zk+YTV z%25D^vq%*$tNjISx5t4r;Z0BOPiKmSN?pgsK^wTK_}%+0;~?EZ=F!EhYqemW^W;#K z&0UuEx1eHM1e11|kTy?Z8aS47le^Yssi;q&rHVq!HLnHxT=EX`Z#9`l3nFVy$g~~$ z!X7GK+M5Wm;3y1NKed^Wu{cDB=;fVRk||4s>m2 zDiA-)zsLJg#5X6ipmAg*d!&K%i2C$Wod*+{R}OUbC-}r^j+ya^z%1|v2BYZ(o!T4h zi_jsuuZ^sGv}~qK`j?Hf=m|f3VcRa3>nz^PFcERccGhy3adk#J8k)tY#KB}XZM|kv zlR>)-ecCqD6^dnpYtgZ!Uy0XpGzu7CPQbg_5?;9b)J@ zL4`xGX8^e6ksqKG+hE27b2wrBgy4(nCI6w8p#h{>qcETa3IOm*Ww~H@Il<75T+f*0 zkZ4H)@RXMb|MSCgHUMbN3!YY|gaEApR96{*Fy`e1IC!3+*Z?Hx@IT~r-4Zth4-SBJ z8wiLqDlrLwasa>%ARPn{eZex60H7M^hU@H^P7uJ=LIhEP8&a3lf3eaN+yMO&FDDn+ zJQhOAC0b&+z{2`h{|5Ds0uv|(Nag|$`uK?dqksgY=29e{hXf(PghWJY zkNX)`(O56~k-E%$lM&kUHri2kbO0!BPjU<&=GmJ2-jj{*}?{GVDb;52{&^BGEJ zMETrs@;B~hgnb{H@bh&@J%CvI#}SET{BOt*`pdt)PydUKW;Ng;pk0VsF68q+_DffM zJ|zI?W%dI1KX^UR-_>Apo;oAO(>g?b9ZPU|fM4u3rFDA;tm@3K&#E z1kw2e{0)&F)zA}1ZOMxf!G(i#wiwDGJxO8FoNLFWNw zeE|JWNgf#F7MElZKj>$x?;+SkzzZZa|GV~I4N{zQ2nHZO+H(I#a1O$b z1#|}}k3yn=dH9T116lxtMmRHVaPA{91Xd{o1{6pE{aFaex3>9T6VtW$c3{vavRtrB7A|2+ z(0dUrXt22`5URiIjKDAh$pFOsiZD6gODbhy2)Q2M4_Fci790co5=96Cp#!oBB0~xQ zcK>0)yE=$&pYKBiNdHz*gh)sV0d$tngkL~j@5pe1r@DxQAy!MO2?OepWeCVE>KH;> z|2*+0>-Ek;eZ6nJR6XDd>|0=`|Cd`T}cS9rMUy;Un(%*`=$fsU#rcd z0HI0AAIM1H9Acs8?0*&?eU5<1C{fGb7779JQAk&2#=-z*7Qh)l_wrABl*&XH=zroF znF+-F1&(P8Ae9^e3v{#POG)?FWhq>c!v}z6fZ*u!7ifAEpjIUc5?JGv5FGeViwFy( z(f?FOQCbdZgo0p!Nfs>sFLFS8QrF!7af9|=Ka(N?lk0`71X#RF1i-}tk;R4(d_tJ_ z)E9{~{+Z7x_nf}2Ve$ZvAds?uRY!r`8Bzpn?-db(w0y^HmNAHk(qgtkwD`B)KebVy zTp#j(>}S9LpVdZz0KNiFaj^n1~?cp?NuwiVz-AaIiK_c1zH>2p%*r98Gv02-_b}=bySLFp9tG zqJRq_>Y~+?BEpdR&*Gwx=?Vs>D{afDu+TH88kk6sQ!4-E3|2i?03?3XNIZYTjwMIJ z34Xu>;Nj=fe{-h(0Nw<^BqO)1i3y25GY(2&@H}IJd&7V{=2VgdcwmK|6-FT~g@gk^ z-<%T>c{YL_-nRK1z(7Bzqk!Unym|m*Gvu%XFhu}=^~eFpaA2B2)J0tc$&oVTgr1k^ zttv{hjC~T6miKZ(iGMwhMKAjtu@F0jXSrdbf1@rWC*uTD%2S|atckEbTMvkeLQYAv z94iW?JOi0SNO}HdoVgLn{{$_h7NVF8bS?yN;Pyfj|C?n_3Z^Zadm^_mfX9<*Ar*n` zG9+H|Uq#@;^(`xqu8>VsksZ)@ZV|x%2fz~pXmsG#^cWDjXIa!E44s1%LPPdICvW zNE1{ukht-Ju~`4rm)ZsD_n<=zfV74#ZQCMhCNu-M4Y-^ZA_LYX;0yEuWVQic>iGqL zC4v`hHUcaW0G1v|R>-SG2oeG?O8^{w1`_}Oz~~WM*na~j#322KXbSyp>0;(D3+eMs zBX&q*89Y2(U{w77+L}gZvu&xvCmseQl7V-NuaF53v|yg95D2N{O3m=sfzumYoL~oM z$N~o$m?gVy3#N-u72NaXG_^DxSR)SA{4aVPD8OaF_qSeQ8L&}2(fza7HBRmy_&mT{ zi1u$~O*J4}AXREnpPiN5Dl7$Dr&9qOhn)LZ7~s*szphT*+5~{-Wm2duXgH#Rh|hJj zWa)tTP<03g0Ure&!cxG8t0G{b**zKt*ojn>1-Q|-0;DJ;&4LAp1AsIG?40^P0`1Df z@bB;j#8ISD|vEXg3M4GZb~f|>ww_(DAu)hy#Xu%-gH zq#l4oh1hZrSpA$QfQ0VfJfYIX0tBhWFq^;{nL=fdK~Rnh(?beF%R&w*Kwd|m4=Dh5 zrhWK;+3CZC4yMfhSN&oDz?i$Nk#c}JEf^zO&^SdMpF>?}`){3iexHSGuz#DX55O0H zj?INQkaEu?mSivgWxlx-kaw|pLeRkW1nGZ90pdjHdEvi{GcP!J{@Ib3@u*zShc3)s zll(Q}VhY-}MY%|*;%~XmiAio5z*{#$PWN>@_~#3^^AR9W=0NG0`z#ztc#BjYXh78<#XD(R?X zxS*7XCcOmZHa%)F4yyr`Ct2GIRO!9FtNzMd)AQ@({1Pq@XL+(4uF8mA2 z9lt}t4`}VCvG(tZEO_r?jWxh(icqUaif#=FhlX*Oc)ZDcAfc zU0ogC4y-0X;we2;$~>FLrxHL@3B#Pro->i8&U*;&%l}L99ix1Kd zq)-XWJ#i1K81;5{p1Q;zb!x0+S!;S_+}>1{V)jsPz2;A2-{E*49=M%tYDt-At4@e# zFyww>*TZ9g2KPvOO^TnaeqFqCUC_g|0>fxEOX9p5P*ti9(k=V z7fqY#DmlxyEZldCOBw{8jrp-Duz|#2RpA+_m7wV`#SV2oHi>#0+Fugb^JqRPI^vsZ zfd>#!l59gz{;c5VRMm%Tn&)7>Cs#RSsoRn~yz*ylRdk#PjBuM*0BavesSL55 zRUG>Ma9@aKd1LGvHTj8bj`XvId)Y2&3mH_z>A3yoYcNfhsqo}6-P#=Su_B1q*5U5D zn>`+F&5d`1aPzv{U-srL z%ik^!4Hr*Vx@xA*MEJmYXk{xj-`=$#C5vNGTQF#SDaX-$H%^c6a#TuOUo#!tN7Vwx zSIm}81NjIJ&N3W@-O=M%rfb0N zgQn4xm#ATMs#TRD94Q)Y!S@|<8rbnROk^|!ELy>>emiS5imy2JlN(bSgeYiPzdh5K za57>`n7~u%9L?nq78%ORHOsa+B3gI-9LzEA@JlN4P(JoEjd7$jP}1Oo=okmc#sxX- zqE)TvV&Se*Oaq`2lBx20X>YDXkte4SH4dX%w zwV+7|Sen$kHGE7uc_m$tRi!WKitG!E70Ve#R$?9)O;eXXN!K=PpXJi4pCHUIyyQvD6;^p?4T^9)4CI^UH%W>?Hgz}f{HE;8rOol=2CIUQqq*HRit-a+f8jazn;mOUK0d8kkfQx?IFxvQ z>CnUw&wI2oHS6F}D>VeATO9v(zi*n~Zt~Rqi{@pbgSXK=`HiD(iRlg7+p21&?I%)e z^_2y)sk8h!TRa~^P``5>J#Raz^%T5H;=P|!L}459J04v|-GaH+{Y2I6N0<_t!OyMu z1w1aN^p8k&*YNk&I7j?ZSe<@I?(|FvHx0xM{HT(%YrOv0rwI2x7Ik~PkEI`WZR>je zV2K4Dd`E!o)`kv)m(LOSlMXySV9%TK1#vcyY^|#xWeZtz(oyGS1mw7uXO%#rU&W}7x3}#m)P0$KkG2*OCD?U>TP7990ji>u69HAMD@sq+{cn@z0^!qUc# z^*E^=K7n`()873K|CvP-;16z2oIuLtW8GF>qV1629W%&$^A7Jxa6YxAzUBD$vJ~6U z&ESV2da)kNqVl5LzNN$(s zx`PB`OW$aS=e17yJo#uDu^z_X?7B*1$D)aGplOo(@&Dwm$tM#tu1H_sj7wl?yq7Kr z3Hu4sToNfca1!lMB&l+<5#@0wy8R%vY|Bhho&GjBzYkfT!mXB@q;F=i>T{g1uWcP1Jc^EBgIe(Iv|@jR!6k&v>Ak~q8Tn-7MzmkF5Z?6| zq%xQegPs$w;i{imX(B$wNnyH{3xLZ($32uHqPVRvaI}4;JgXQ_Ws7^4EW)y z4o|YlPX|k%O-Tm)db+NjE0I@Ta0Lb<{eCw>Ng@4$#l%@|GW0BvL)5H;*kqJi3lLVZ_0kG7-gJu^ zK>)V=17ifbjUB5wb&+wTWsLTeDs%V^nADs&0AyL+r;+=)S^xv&0-E_TcBKapG z>j&H=Ugb0Oo|M;av$@OYP^0GXhPY52s<*|5hOb6udCYlYZ=1WbXuL58<|zVnHcvs} z`S@RtePCgdq!drSk?C}NxmIOAEf`hwTkKIt|2W)qS{J!5xk!30$0z(W=GVlcIM}B6|f+7+tut^yctQ3yASrXQqBFi(W4ryD^_LR=zqhmcSu#KFNvK^br`j^!a09u55HF5AQ}i=W~gr;F0B zFI;P0%ZKUG@P4{IcsJPZ6>+}!c?b36qPH3JR$KnPIaiX&VEhfy;Q^v>5qUR`?=e_c zXSL3KoSf)5uzKuLnM4oe>8mNS`|?(8P7Njx`?lAw*FAzUY>oCmZwhw4KhB@?x&7e$ z6u(Y^&^TYvFq$$p*$@?Il6$s8MgQ`nnRTF$MajD#6h;&$YzS+~Wb$8oI9$|ttb~yV zK;UY1OOaVOBIGybePRk?SEmDa_m;c2rYttZD|Wo)FK2I9w&w^48H79vTQRvrMQw72 ztZ?em(TbBN=um^aeiAK>%ZQ*X7P@DAb9Mb-s-;10nKe6OTWDlDmBPvz?wr`uQF5IY zRkpCLv!^o_GMMmSWoh`vmA$bePn<3e_ZRBsH9x`RE=bQ3DeaQD{E=cT06p4dPyfB|9z6^ zc;J;7p^oY7yYJN_fZ)<0ljLlN@eah`b=#FLc30&@@X*yHmeG(dCZg$F_7dcP#4*gY zndypA?TJPHfsP#c?OM*ClCHL{^jVK91nMeYsGuuQIBIATPj7RR!k zV5I!KB#HH7T;|1tV{MV!!ubFTcw+_E7h4?geKErA<#O>FFsxc3JEfU;;xa3 zJfO5`3hk8pJIo+q(W_n(&fq&KU(+=%Y4FWb{Wux7stk9l=3w_HWA^k|k%!r1Oe^@h zQ81RX^6#KEuiu2;`7*)@tlOaE?aQE;Eh2q=jXKu4pGUTRa_qMpW{*WLNjR2oW2W)@|y1^<(c1?d|q~dv8;)0KxTNZ zk0Hi+v!j;su0a^BndtIL9Ivs(j_{4QSit>pWo!Dg8w5*NC$16WECHi7mh6H4xi}xk z+ZWvvli64v0=Mi9j$iXKgI5DVK@m)#(eIx)RwcDrWv<-Y^2)JDx0G zZZ=w@v5ui|253M(JKnA@RG+q4E9Pla|9SBFC`ACIx{QHNp~bh@r-w>tkm6%WBV6Dr zTC>My@8|`e)C*LTK#G=;!f;{giEN}M%oZmj!i7%g6ltDJ$+C)j6%ma;lj#2Yyb_s0 z3tWQlezwrVHBj!H%Hg%%e9^nv z>=2n87hFZGKV64gkkrP$iKCxRHkg!NCtCvXw8k96L!a+3S%geutJ|Nr(KF<6&*Z&L zJTWH_h+==?CwSZ86DycB>Z;DV980Q^pVs;9fGSxKiKl5!&crj)w&LEz0=3v>+2y8m zdTZ_FXwa}e!-v_|1DbZ5gK(YqXD1SSPKiZoTtY69XzDqrnlAPJE_2EtKNijA* z%0rdfQ=c_{o-@-e>8Ha*3a0pvFwHaew zRC|pnfsW-H{OOONx9J;Al{gQ&m{=c1Q0(yKt=x;O`=3e+RG^V~9wOG#&7W%ZQ6Neurn@WS)xcJjD7!arg`oC2lETHJ?6)4y zaj`_}6~9^Vl&>>?USac!6(UG6*{Y z&Eq0NHtT>bU=C))Fxv|^`?}je*^fd835S~zY~MrBl_5FV&ZIQ=o$|4y-}t3=rhP@7 zSbIViTw2<7Lx$uWKfIj7E^$6zAWas!H=jqKi(m84+B~kG^>#!J=b_s*QO94FSJ_KUbAP`XI~=pEav;cUfI6x@l&{6h?U<|OPv8>Ul6FqzMMxH ziJUoG6wdyPmkPUMA2ZN7i-z`Brib{3el~xwx?)ORRs6q33G%KmI>rSx%LO6Z~|WQE$R7=o zg}OOH(hc-wl*UrK!ZNHrR)*)thHi=>?nDd85+bW3&cD(^7`xGrJ?a3xoq0+!U}IzC zVG=BVXRQk-Ya)Z2R-C$)`vL1?OD}%MjM2Bxbu7j|;ZqBQ>=v>x`UvIe918@`R#~&E zbsQbj8Oy82O;l0d7%DwhzY=+g!(cU*iP(r+{4^3(OVsatRGaIxV?2v%G|$8mqtt1R z^}v=%kmDiqef2>`q?X;tfpK<>OP-Mg7$!pk=Y+7h{6a zFW*`*l=gI+zL4Eb6p#DHR$lJsd%nh+C-Be8k+zbEkb9wl*JhLw&8dn}a8V@Vd2onS zFaFX;b|oj>u8e=`nN$JjBP);bDlE@FvbqIf=cGFMv|<8CKTvEGl`@^}5+*GKAe8-Gq;PH@c(j5Lv1Dv3<= za6aswTksB<%`I*EV(-!9AyzZl@)Jc#C*7k|MAm4$!L#~GONpP3d4(%FAbBGg#V+A0 zd%>e5Dl>%mOBdUl{k61%GcUUhuBH}O>MsI&QZOYQC$nsr!m<)iopR1Ja`tpv8^2e` z#uTH5#OaUN?$LNn)tV;Vp*8o)oRTXRA(Smm5oY4xkKBCw#JvLf|<5S->6juN7AsCx5r!alnWVxQU$D1=G@D?0IttD ztW}|li^1rO-wEvJOic2k{7NGjOuB+e0_xds?HFNH^*TyI=%sFtYfT$^KmG%g)}_XY z&-1b&MNJ?cvl>wz+wayit%Tx@ON;^LQ;>{msnp$qYI5E?g+31y|4zPTk8BI0udSRO zeJ`jx_c70CS@9958M;WujW$>lh8R(lY~eguu|`wai|w_1J5c9ES1o2WJx|dROA+mE zw530d^&o)HYN-u~k6Nv{XTS);MOQ@bxN%ZcJDeOUnTTpp<&j_v3RZ#_ReLX8z|0h^ z^lEJ83<=9Hrx3w)5iRCAtrTXOLMDqW(PVklg^nF?9?&|B4HcN8oswO!Brzk`VE8C>#2zdOApZ$Wkgu-4?a8A2E7eFO+zHXJk&bc1P9ksQ>hZ-cD2Iw z_I}t4GMj)_U;ojM2dEU+7$<~_$B{$1Oa`VJhDG*{g+a&)sjX`FMQEY zIh8XF{})^59gp?*|9^W6WnT8)o9w+e5sApih|EYC7YZd=;Zh+olQOb5*<{abLiWzq z@4T+7-kvf*zdCqyB^SZ9v>wX^3-&R`&WAX>OU)qPb;)xN`UNA;XN?I9& zr5B7F-sDs4DZ-?9P@ZOM!_-2dPP99huQ*seJM%z;CPKD42z%64uWdoesd*VAI6A66 zv=u2E%J|uZ3712lZj`7vE~&Uv!3OPzlW$#PC1cyFc;Ss9N@KVf&U5?1WAVLx=?|uS zc2)FnpK{Hdu!nB1!idFMf1M*Dz4E*4&&uFM9p+_n+jgATqK){JsWkyt+Dygx>3dvH znV5V(nq4O_W8~?UmWXG0$yOeEu#%)G8X^nYj%=aPCRYdc67YM83e)s%Z zpQ0GYNvZc#_E_J2eVf9rI_3OQ_R6U04>FD)PlWk8CZyc;O@6kDzYp(suHovF_Fifu zs<IcIs!`+kVsT-4LTZ!uSg>+GUl-%Q@tM{<`#`@~}Eh&FIO1 zo5{hI0-UoAb;$sHGP}(EIYIGHPMWV-i3C$;+ok!nN5uPfR>g;=20NrivoR7!~H7f*++o!)A=8tKyR znF|y|;RCQjtMje>h{6VU1qb4`_P&OIj<^@)8Q*l4tb;Ch^i2EfFV1NZhqr-*s3(vR z?fx^j7qX-faJiEU5({g1TOs0Xg~_qO%O$bve{nJJ5#+HX;6yOFf!BsWMf3pq?y2~a z9U`zmayex3Uhu{V(hCKz$w2N&2<(F1!8OG}{Fun!+`XUxq%=iULMHD81xSbkNt8kV zAjLw#{g7xS@|D+-Gzv(<6cYjVp-jHuHnJYJzhsqI(hxJCwm?}11_u&GOAnOMM&1Lo zLV+*BfCYfk_<}n^5+OPb6hL$uLTHB^=wpfjSCKh&dH$aJeAxrbO|Boe9 zGG9;&k_iQFqLTR{JP*i4Aljpt1QIUY2LB}9Fx;Q^d58@ z!~}w(!eep~=x&=oO2~o#PaPD|n2+*k*O~;CQW{i>ijOf>QK&8e}XOVJahCD&~+_bgUpt+!U!f97YX83k2Vi7BHc8cE6k%{!$4yYauQ-Akt7Oe=>O0a zKs^)C6;LZongYUzSx#aC#Ep0u5Gw@t0l2~m(J+F=f$(<5aj6J=4U<3;7V}rNz&md+ z1ongw;sEAQSQWf62hqJjER5(!zyQSt{+l19cSgXRIoS|}otUl_SZ`oKKn@ie6ckz^ zj6^Gtw<;wmLft5K2Hlu@3G!D8w!&}_1@B-W1*{l?^osIb=(RZ^qNf%14pErOOH#3! z0=o~rh6Y}uhzl@YDB=PvCqP^vFWGc5{e5j7{2s;wwGEuU$Lfdx@6F#LgqF1F5ML%} zaS)S+qU04z=`dlGMToqB+C{ez`0r)9g#ZMPfJQ_`QEH_Mng1*@M+4poi4TD^#L0+Q z30WB8ONb@~A~g%P2-(@q{YN4J11Km1j5`X-0RBTz#=9IC$V?4F)lR^eWEq5I zAOs7M!2+7zgun)20A&ax+NxlZz|iZtIUqwgC`(Y`Tn$SGDydK#fX9GlvsgnEHN6=% z($MV0egfZ1K<6gGoG2qQBS0<; zsBPv2l>5lk=0L8L1W~&ULqTATmQ{J$tOa^Zyd8(~zk zbI7iz2!jwxyENf9Y9EQqlyT1GK7yel?7w{HU^>K6`jViQQkR+{vH+QlxBpn41YvRt z<3c&;0aCuFXYsy42w9RdBj%XVuOdp%V8c*ni>bx`=SXyCyjSB9oLB^`#`ER|#xRWV9lv`u}A%2jc}~$(K|DAOq-& zDA$p>&7&x3QO^QTNfJO_J;NZZ5Tc@GM=i?#GMhuyZ0;}ss?|&f84|)Ey*aYSO+M_x zNxK9%h(|QE$S+txLVEzm5#gi;Bsx8A0~yx0@h{!4a_9G76goMIjDs` z1>A!A4?YJ^p)4Tv%O~akhWG!Z%YzkYb5Isg(&dm3kT5i;YJ|=LJ&1uk?j@Np!h=(Z z7-67>>Ui)9*s$i7fCfA5BMer=PMLfJB37L?6k2f1SS)~}6-!!|2}1rt0BOvj;-+;O z5rnn6CO$$!6E*sVcA)=;ZRkK3Sd;c8^6L)s4zz25M;9`KIrP&2k}e0n4B)eXZ(Zt) zB#3Z5BwHtf2>HkWq?O+@u_F}owBo=i5edACNqyRVp!NzZpfZ?49~8KdnB>5|37F>?n1lm1HsZ@2+AX9#lw>(n8!1^1?4h!mgAX8^xiCVu z7!c{=&0NU%R)l2BE$)J;Le@n`%9cZQk+S8W3OZ7@94bLFmqmZB5g}^qY573}filk( zN+*z0l-3)f$s0E*Q0D+Z*Oe+zj}q{alu%X){PF@FB?pgpk5m9gZ#vUL=ppz?*TxPw zUyukL@!ejO^)-UU;N;T()p@p#xq0w)?)ZWRl5x3s6 zAj}aB?W5VCk+n{bMGxz}A6R?7pZ?)$Z}mb_exz^tuMeq?_e$-8PHv9O_vMqo9n_L5 zgU0_Dvit2T4~EZKim25+@CoBB6pqcxN+2}1vqW1WOrA>l2KQX#_6ulZlQXARxe{`A z!`4fSCdcPFm1X3$tQdp^Yoxt)C-vr=gI$_xC$8Kq?S6IXrG5U{^W(*u0v}Rqtalj` zQ4$8Hj$Dha`-N2eX$n+2SJdylG$FtX`DtG&{9dG8sy)xaY-{IYu~ zVr9dqNTTPm?+$!-J*O&jAy#oh6Z53})=AKP@M7ImPV$PD*Qc}~f0Mqp#V#XrwJ!fu z=HJe$=0^7y9#T5o~6f zH@$dWhmL7^+ZK1LYC^(n=TbHOfAcMNRmdv75EpR_eQS@=Re|nk;_;&B75^}wz;~Fl zT~&WXiE`J@%%W$^w;e?-4Q-X_H2JM6kEz8*nVnMldxA|dS!Um*)7Ew?bJO;;neY1D z)32i6vO<5%4wwBhc=qlm<>sHxi_b*Ur>QA%(dMc2g*`0ZHMMKpcj%0wdDK1;s|Y+X z;;!!TG4K`$2o$|zVrKKC>$SjrBQ?sy?>YL-LsQp!zq{Nj%zd2fE#@xpb<40l$iQj|2Og+9BwD~nKV32db<2Ll<=&~0u(3ptri2Ntc z3e~rY+{3FFUEiMh(p8lir-f)&Z!08lBtFwBbm7Xn!v4J;$K09MT=DRejlq_1Xbxt= zcx~mMdb5&O7>^7eoOLl2mX=;I9C;)+qltNet~($834zrUtsHeF=#>*~dL5dVl-rTE z`rR!qxuCjcE%C}h7$TOM}KCa_ToQF zdz-Ygk|WGf?yAbpvz)lty4O{Cob}w~W{fW;qi?Y0LxoJw`8K@z`$Hmc4c5*Y!_oPp zS;USqtLPNr@be6;gqYUS)`7(G>ew(XYV~I3>QLr+{4h-R$*FIz@3}m$Ysdej1~gi5niY0W{V2k?`GS_F=j3X90u?fvlI~TM990 z-wj8x7E;PSQ(a|}-TYo;_kR0_G!~ANqd3D+zFzmi(6m02EAJu0kcmig_WjSfUyP>@ zI7)JZr+lJ{Fr>rpllV2{ORajwkg)l9Rh+Ie_#ZgstBmtbEm7hP^ONSCUCN6H^3uy- z{g@Y+X1)er^DL0EdCL94xg%?BV%~qmXw5Cgm2N`psd zYs$Kx!~XR`@%V0Y{ukx!Pq4QmHX{%(?J&MFc5vNYF+<#B>P0Y?nu^>__n&~@mA5kS zttCQZzG-Q(5MY#d5xjqMaZ|O-$*%JA%a#}kD?g;Mp5=rq+7>upl4gdQ@ zx|C>t0PWpL2SYsJ!7=IUp{@*_xfyj5lpmKWWNql$!dv;9ABSZXR26M|3T*I3x248Q z3nWC3%#FfEWjC_7D#Zyn)RQ-u_tp|6eMLxOF^=(_)*Ly7iWg3t+w~*b(Z(bXrY3!iv;tkJSl{6459a((~qOs zRR^OZYgIQTvZD8F*y_^O1Amu)Ekw+m^+fj)2d2W8SM-l|N@M4i_gu%y&VnW_CbuWr z!)k>ZaF2=_VPZ#aG2Ly6l6Cc0y>lMh-+rP-FK?$ORv|aGab12rxsCKDf{HN&x+}(R;rI#S#nBCA+2gOOez6dJV>d80)5TB1y%XUU z)GBlhE_xhGmYfhV>ZF<=Z@U)Oy%S@dET(tqHy`)<@h%I8$Ka;n2TLJ|=+3)_FZ3+E z^aul%c9U)jHS#7#J0gaYg<|;1G&@9NC~k@g^Rx%MsE!sm;kT9y`g~0`?xQfK?OOM~d#ILa@(#UJci~lq0qRn{E5{x)_58mVF^J^YGp4@f|mNg&iQE&=!Jd$jh;u8Qk9Evvl3FNd7eVEKRdgxEXQ$D;mNs&Pb3Npc2y zdVb!E;vy=s$ZB&iC?GxF~b3d~_zD>^6MCdMg=ABH!!ym%(lYZDOcfQ$Di z^O^uHr>;yKA^LFZ?25tRV*4ZhSt+lpE9Vqz(!1x`y%qg*@nlvwLT|_<*3wp z9Ax%qteWu(>?u1uk#HNdem4KOFSL7K5Mhb!b!m6>{q>sa!Z)|8=7LKheTT1P)!rOc zCZ)oAaz4I4H0tey^RcAEJ?avTOUuI7Mf=Q`Cf80a$}w8k)^|xUKFl#c6=ZX+>8GKq zwk|s)R(w0=Qpw`n!%=2s{Pq#cva7>xm}2kgyQ29j_Ng(uQbx_SpKgbP-}L2Gg$o;H zGQYSy5&N(bSf@du%KB4CRbB3MRVaLml)~rvQ)${$saJB&xo|ZM;d_~LRuAi6U&|5r zI#ykl$*nbocLD$ARDtHoNt#EA9;aSS-gV8x3T=)-{e3S#le_yq)APn>*T4uOo?QoW`f^%Ui<>+0IY&h2kF0n!S4Iadby%W{^ld~v@ zfr8cdMZhIXzkT(2FDq8PNe&(c6T!pq46Zar!DM-s>yQbH@184c&Fcf`q76F*NR!^e)^XG4|+4Y zE4W=jeLnuxlW_lEKjnN9hBt3&n>>?m$?skmzUML4@TM@HUdxU3$#!AKS0H^m^*H5o z;GWF}dcd#^)?`FD`npKNHkDDC`R|_p=&iB2 zcF-GOYMoTG<9X*S;ih6(!*>PyQZ~31$u}ayrjw7;BZ%XA*buz&===D|%jKScyVe!7 z4TTqQ6&ZY`B&j|0k>`BXvMZ~#Oz(v6jfB{R(&OD~83=D9o_MpgVUghQgIj%oqfU6O z*Q(`P8)`+JefD_p4tpc=FLGe_g3VWWw9&{{pu0#%B1MvlDrQNtLa@X zo=i#nzRmr_fy3Z>uVp0uHTG~Bv}~gr8qNvKoMiS_a}8(kKk*fnrY?B0mZm=T&z-<5 ztMoo=|K$8|Y!HtCEvL*@x5=CGW6|R@4$hK1rFtgermx#qz1=0BFMDvF?@`^o^KKzI zrZ3Skx=YFT%SC+I;%}VEB{H~V79~RCt|TL`gPoRw47$uv2}442u7BP$R!2X>TGM*h z>Y&`cI}`Hy%^qtTA)&fyEf=?cf4i$uzBB1glJ7}Z_Ao;#*H(w^xckqLzE| zsE1BQ!ybK;84v59$)c;cQZei+-F>gYQ5&U;Fh z@?|(A*y-Yg<*!}Y!R4O6z= zkQ0F+U%p3E6bw-uENbSsWa5LOA2%n<9(Ybs~x~DR*EZA>ocVm5*Gp8gL8&mdYun(8&ym%o+Ye> zx|Z%&GfiHLR(VEEpkW@%ny}B=wU43Gy0c@bXEJ!M8tH8!FpgIK>E;y&{apt5aP`>D zO@SJZJeA&Dct`rdb^fi7u;wEJgJYVWD&?*W*&+qmh_uxBcX+nB5AGW>9xxAEGo_)k za<4h+5oeWz%!oAcE>1oDXdUs$#pzS0W9}Z7>(ct46U1smtKjbsMK^@1(a2T`Z14mr zfBUAaUllj@gi@ZPpXyZ&`j;O(@M>iO5lTl*a)zo&O}opmO)CTFx6ElFp!V&cb7 zcuYMXI>?2w&)Z=|RMe#6{YafulU*XV>sB|9o9RmR{iX8q#`y2Pm)ps-?wfEio5`fK zhGlDplNnRSa#4;4=B-Z(ydIL;PG`crW&T=2|qLf19Byyz0>QN^G2YoF(r`W0%MH zF?`lKo}a{Bkb6$ZjFOvoIpN}y?!Dw*M+b`_H!6qO&BoWuW3JEGWy%6;U!5`sgfF_R zQ!L>~l-1yW<%q!Npcu-3Q&ezk+R8NI$D@&nAct2fb@~#t4~171vK0-<=HTuMIn(L1 zOR^Ja?d73vCgI5{517756uR2O#V=IM4qiH5n|B-|RQBUCrIgm1n^c6P(L5 zzP?hfDtYy}x(pM$?p*7tF6Lr@&-G~**~Fcvrg_iUN>L7}cRr~L5iByUp*53UYkwT^K)Gk{oY*(vU4`W&>-My>L?vJ=d&hv>`? z&arb{FF!P*_p~ZB{Hc*UzbLF*uX-Z#=#qH(bagW3Bi*OFQX#V+?TwVNk{r-1U+o45 zVQ%+-W2A|DY(>6-OE?%1{EEi{uXlCQT@ag)fM9M@@O^3JRT8&)c--coQtMrYts#?M z2G$>^?F(-&M+CObtJHoriXYA~oD;g>Uy=o|cw2v^QY`B___AMnm#{CB+uk;B^H!bO zesuAqENR1oVPEytSX+$;r$urxr(?o$h1v^ubFMPIe>&>87V!XxUVoUidEpjAyGk#R zTK=Y+!A`D^@WPp+vRdi%$a%8YP3I!|;MX0CPUDS^q&B8UlDk#~OOHPNx^h#k#yzhk zyx^e*eM)E7i`$Wz=dS`3?7EBLHQL?=>zg-YdbH(fzv9Z6F_HaNgku;j0uU8S5pqh}JM;9vizFiAC<6#Actx!CZ5d-9C(mS*H7H(C|GCDvm(+M1qSv zb9L$ry=n?Qc+q18tyFlyYm6I@j7nVXm+Hs~-(=e}e;wwd%L#L0{(6JoKFpO_W}Pyq z;N)Xh*lT};K#=@>`Oc|ULTj;4R5MT5tj?9ITf!dVD_0+L+!-{i&eG#*H2-BHfZGrp zszKA-`BIa&aV~a@hoE2s#-$kFtW_j*PZB3pbqnp?8OvOpZ?K6MylCueZR4hg#D;77 zHwyjOK-m3=Kh@(lxINWGm=7vRBj2KJF|UvIgl4D}Y0!6Lk=gkyTRq~z(s|qSVNI#T zXxEg}p7DFL;0ilKqwTJX_5*tA+soozp)s42{OWPH?z>0{j!q#Ya3i{YaK{9E9;0OM z;WgH-Dx~%s*L@#ou?MGK?Y{3b*?s+XRq}TKQF|o&kq|{zf5Beu=Yjd#ON4IcjiJO( zK5t*=da_-se$U9{Md(nIKn7N$$($A<{-ON7U>qDj3H(^c=DV6GYy5b5Syl0Y|FZm7 z;XZesnO!O_*dql3k&gw(S22g9Hurv8`tA(9Y7)`)IeSI?e3PvWuBo%sJa<*l&eymu z^)|wWWZ&#ELb#kFN2UGQE7EL7fvGoqbhLJMd%_k%x(J>FwS+ zeA}g$vf5%=kaQsw!SjejCpdNY<=4~GjO)wI{q5Q4n(8j^EO9sjJX&!2ve9uLF7Vmw zmH86mxLV(6ntHn{@e}@CMzq1ZYy6BrO3(5(EPP+)rBnxh(&qVmt?FK$gGlR>Tt|$4 z>u+qo>ji6$>?F30it*E&-eX>qUb4jLIc6^+O_|d#$`%N&>)Fm97#L*tnO)8+6%|Pwd9=aRq0pZ|6?y1(Y7=gKILb+FA%YIrm#8^@6!DMbH$y) z9rH*{A(G{;Uu>gHwYL67%EeeBABjo0Ml-_csgkN&i9#8Hn zM=JkBA4_NwahmKthabLuJ|K?!<#j%}dz%9v;+A>y8@}MvOulB{VQcKvSy7q`r$wIE z5j}Hn%Rc@rl`fR25U2Fu{r*|wIt#aN1=@%G#@ZC!G>p^f)Q9L>1}dvK1U5pegw-UQ zK`%A|4%x6aVD2MSmB8hi?;Os3Ci8}w#*px5Ou?_j zY)5b;!0~6#1iSuS_?Ts|x2f+J{2zhi&ttCBG(6STk(y5KCr*gD^2UkiJY6wm@ZAPs zm0Lkg$j|82e9hZ=+_4Gnjc8cOhmSnG>~v^feQ`^z#o^g-eKNW;#mO^dq|&zc%=fNV z+dQ*h-4Omklk8M5bEVRev?V?6aL8WW`po??;e74%>UK8Kfhu^LvhmGqji=mie>xej zlm-{7yznVI80RA@JLtVK$|?NO_xdvVxBd^op=+0<$v5+Ff4X{R_j=+^ZeyESLE4od zPP~+=uw-$P@2zl|{ZAyzvw0e?ECyUc>*=qse(F|^_|8T&Hvgrr=z=zj%%WR6Dwk$s z2`$7i^098OwUBAmHF!YjV=?_-5%Rw-m~SXAT}ggQ6-w%>9(52=f#Y(jBDP@fWS_nN zro~mpG@R$Rd>7jar>Ep3cHm>0QtDP=YM<*) zX)Pz?F=2z`V(+k2nL9SHhtqjXZevd*V?FzN&6eP44s{*_=D-rCGP%O*mLV}Bx7ljX zOv2(iqskVp5BBZ4KOQan*%=SUGrjB*&>2tOHZWUxIADah!!VbkY|)I8OVu#Sn-h?x zeL#6EaYtH9G!_viPR9#pitY!ddD|>n)6f5C!Xo|$^C|Bzt-hlOe!RoHUBUM z&gX|#IT>qSZ>A{rFz(d6A5pGc(D~D{qK(swvE#}PjMzO|-|YveIn!;VC?81SgB=WRq^XVUvQ zlqHtPWkJ+&gwET_tbre(!1XD->VVX@Ge~>y{)g3u~R=^NOHk zy2(s7wv4iY_Ny7X9|iL{vMY29zt53HMCR|iI`Qe%FyapgT-1l$R6Sj4#ji_Vw7po>6w6s+Dh(j`~Z=+y9W>sBS>uUy%$pW@?q5`Aw zJQcH5L}jav%Lixr3X-vv4d{`DyoCG~@-BmW$*oRIkiOg5)#57N^m>%dX956+Hp}ybJZYYh*+n@uqS2>gV z6*Aa*7oW#|_O|+PxzbPUg)vHe^_mbyFC%8jQ`&oNMm&30 zcphfi!u$hLD<=+q>!IQ3fA&{=ibNl#u6Y zvBUGHMNul36NHMi5AN^_ZAHx2E#Let=J-p+E?D#T^#=8z-=t->v_lV$M{cpuP!68l z*WFMzit26H;4(7jn5?mTE$rerbB_~yC>U2C(poL1P}9K{eJ79i{LWfpRP#v0;DRT= z571hT>rb_qGn2_S!i4uFVumW zcUJS}2iHorQnDA?i*@uwa-OfN!)=|_a3?zum3(@>-5bYSKd}N zC1CgOlWeCOuI5=f`k$+ydEUdp29e!s_ zZ!+3#z32D7u%>p}xb*zl9KXEE;v6vptmB&5$_oo6gnfWWX#HgpU)5391AiSCr4qEA zW}M2Br{O7k%KPnP`Hi;j!Tu_X|NMgwdAzlg)7Cu^l69#ID-OLc63~&udsuD1x1l&MR6W}=)T#&FS z02F;>07wk3PcuN^7T^>!`5|~Z{g46)PlwdY0#X_9)#MOlp9T_NYozynt!=`rVMSsZ;Spz@uOL(# z+%WWaB$^(>V2C144H4i+95&JqkV-xfH4M9NsF4Q+{=xYo2p}H$577q7pb()C>ZNPb zLH>h&p%{JO?!Pk!5T6f?FjJp6>X!fT{A_IzXe1#rANu>>fddH3hiZi2|8*uV1m(55n6hQ!V@E>~zf&z&Tg048S z3nA*?XyGGf3upz9?Sy;<{9$k#J3$41o2)kmWE8~^ihy+H68|tcFdBd%ggS4?MJR%( z>6Dd1HV?sr)?KneIG}m5&)TTwLC5}~gCM|>=pZnfF9DSDKCuxaum@4T1ANe_;_aa9 zTMSS+Sc zI1i2+pm0GjG$>q9_{>! zq)8hh!-}PVLMPMaRU$<7vMfJx99!|6E7E!at%mIOUosFh^pyQC+6-Fw3kRZG5`$Hr zOh=5!Uqg!M#nE#E8A(=j!U|F)Y1Y5n$_XE&fM-NZ3;;$Xp9t0jnVmeqw88LF0pU6L zrmQrwX>lABQ|vxM+YO=o;KsjbAQ>C?Um_UH#Dolli|@>8OC#o{uVEvoc2Tp)e2>}s z|0j6}7<^6Sq>z=!q9z4YM_<%N@q$pxAyYDdX$6r*4sxugir7QhJzS{hFEa?7D^^2d^8mI^VTZs?py_!DmPHIRP&`f5mWHAlsA#T0yky*U z!V1MdvZY{gB&}%!-Vf|9>oR|r71*o*FbFyf_Mo^}Kq(srQ4u0yW|5HrE|O3dh$|-qmBfkR10~#j5kiE#2sK+d zo}2`|=*gHEyVgU8eZc05FS6A=!=nN$u;1(0v0WpP3H;QyZmr!@Y`~3K zG{|rO>-9T0OfknLCjm8N^Bl*i!rDuk9~sS_EwUU?Ap3Ct3uF)~goH{!=v4SR2!h~a z9umYjuN>H&!I;XCqSn>}KDkV2{xdpcQBjD4QZNPm2HLSe;~2W;3U&oWae#J92_nb- zweWB2r0YN&vrka&1UY$eS`-j53}(fi>mPRv4E&42Cb6qRh=fpLB=b8T0CokB$E<`E zt}3{uNDWaXB^_kzWR$}Ht$`3HF4V|*mIGB!#b9Cx?FLIq3)4F3E+#=ms*Ic(vh4w- ztEjf)Fp2&*@blubU=0HoeuBOOc3KLWBoOBV%8nK3@^VI4(8UZ%S?GX4$PzJfI{}>r zknU$ybar z7$HbW2Z8j!l$ zZ8=DfR4Io0Zbkod>8sE_4A#|@A~@F}Dvk(2GN{6m!U&x)C0ck^KPIKhBhd%9c5F5< z7<(2}{2$nLg};&OnVl76yJyP7`<2H9oiIRmF6l^LLks(fM8OJmWyE z@#pUgEH56@u=Mg5a@Mw;!XD(moYdi3Z^<`4Dbr4pX7{IGrc2}GS}tm)JhTd*b;w`f zjfk{0?(`n%&@k%Y9Kh|%xia(idi`p!&mrQ^pPM0na0lhpm*E>A@8B=ALWUb??j_%Q zUpo@v^eG5Q_bC=I2iM+MOEL{VWn5cLS0X=4E{3f!LrV#Wtz*1%$*Bw zdUl@7TsHx??Zu!i=OBVfH}>xuzpLJ@o1RASRzJgT-ZyS8e>mGII^AVOr9I6RC4XL| z?f9EPNr~sHgQEP|T$!5W*GE5CHOXY6#JmfVaQ0o>ltW1V zP-267@(U*2@IuFk(px!@cyG>{Hpf<}Jo?|s^0SBHbTH~@rpS9 zDGg=cv}Hupw$Z*BsouWSQIW61HwjzrpF7|6y8FUlY_V`wXZDnlPn^5V-06l6{rpFnusth8$%LG()E+_nTJOEwabH(pG_E5{HK<; zy=klYwrAU1nlcfoDGpz#r@n3et{$7+QhC1ZjAd6m+qKP$mMq=GfWBY(s?mjT@wWD+ zmTQfyjkACDB>y(-M9RIel>UV3-Y=W8Fa7Wc44;#pO)l{|0hhq7>QUma7Z-jj7W)t1 zW!os|q-xNps3;{_-|S7*8XEnb7AGCM19f*LwQxvOzeys#`e*|4{rZ}YEz#h zwi!R`1wH+VimqB+*qtsDp=ktV(ac$0L(Q-K3yL}C$+G~pnGZZIo1z+bM)NUzSRKE> z{VEq{I$B14AGj@74Djq1iqjl96!$kkb&& z@iKVEn&BJ8+pKq_7GD_`?j~YiFI=a?ScSVjZ7&>BbyFT6PFRS4;50Ryvc($V&{#bS`A#VvpZRfHRCJ<`GGa~gF+)#Y z$HsNj_s4EZ@ZCh8-47aOi}1rl{@y1?_V9T7>}x50WNCpr`a8tZ@4QWyf&nw8JgiqI&@H>`Zg+1aAYA$Lyxy0O ze^`k`-Nm&Qm=nl%J8C$G-tdjG7rVVsdjJ=|Uw#s5`MS*#^N);`Av~y;Cw0a3%7|z; zxw+G;(wN4fCJmVpTyj+%>DG@-X&SC;Tm!fGd%Y{0r#I-gocL_2MLTXk)}XIEKc1F2 zrVhOEKGAHJhit2d=$c^itruIojpGHzFA4~vRJt8=-(`m_mb_zqq>H5LYu;e^C?Gpl04$Fx^Y6burdm#;cJP!+1Y=^wG#4 zKICBrQe#=93GWfiReN5r*bhs5G+9xvH!8V}S21(0iQd4wHPLd9p{&D_K$DV!&c^x< zXSb8AYVQt9nKqZwRg-IaPI~i|Y}olG0`Qv@yxJ9=_w^^u^yvEvxJ*2ARz1ErGX{%# zqmg`3b}MuALJxnSJV4X$Zj%=Nm($qYP+CT5R6`}>_ zpz|I4Segn)V^vdNh`oCHd}5U*P%TB((c-YPTsg*pESo#8T$^&h?^%i=omC%VQRz9H zhbFX+$sqHsqW6sxF%#Y&AMRUETj?Pu~&J4zm-=S!hm9Emh|VjLEsJNLTr% zY24twF6xlts20-nph+>o%yazxp1SIFLwGP+i?%kE5a}bF182D&oAeoz8HRyHTQ~Hl zv-X%U<5K^4YPSy_&O0J6o_=v+39ytXD>VN=>Hd-8-R*}H+B2DEY!5`O*Oq#2UitoJ z9DRN8N0+$#qKJ%4*f)%b6Ygoc$xUP3ib45Dj;F18%ymKgw%a;5k2Lk7s^$KK(pvt8 zM=sgI`pMW{-VKkaYXzTKFuMa%h zCO_DE5y^A)1!=T>X>8qeo$wEDQFk$%iHe%boSa}V!xWqGQ~#>R-M z%V@XuV#REw4Eol_n_khORMtn7Pg0X)_?O4iJYNS2UQ?(U_va5REts{?+@|h$_EvMI zXoe!5jZkL+>-&B}2*E>>v#FbTPfNGqxW6bIZEjse3t6tFQGdJC`c1n|fw}v2gX9kT zq=371^w;wZl^Ecc-i$1>V*?TRX;UX6ohPYbZuQkS zwpkU(jn>F9gOdUS!ZRS&PI2-IZ-8r|4z9_xu(mGO?kozpT zUmr=BCmAL6P~9cX`tnrN3P(3(ma68w#NI7Wg0GQ)aBgY6;@*vX5z;y5Y>arJ7*=#M zEeCA)#_pxj!*znJ+hOYG9rnxHgRIIQY|k!9ZDwHxZxU&Kc@)%@hq14!UCz7`!3!bB zw%W3a!~SC&J>`YV{L1rjom6Zko?=;~!;7xW#VKwQ&At66-z*;c)o3Y%3Xs``a=5*_ zdXJ~#zOK5O;qv_}QD2{gaPq%z#a0- ztgBl}=9O&0*Mhe3qsI8rU#QS%R{T_0B17xvVN(92t9=uTT6jE%Nj=doQ_eZD`M$L0 zE^Y%2{E5{qwR97+PL?5)=ivc!Y7Keq6}B|tpP3B4>!nv!pZoF}4Xd%&m()F*5u-AR zG`b__jJxxWPLX}L{O3jbu+oK%<`uuxyY^3Iekgj`kK2^Xc=-p{9B)rD9-==`B!7`+ zxnZ6dT2T}pg`cNpM_Q-Bk|)k+P1yI#Nq(D-N-vP&zyGhtxi z)_mgMn^%)KB}}?jNtT_2Vcizk_9H+?lFDS*bE1B?5^ZClz-V-FOp2o4DfOOOY2>fH zJ-GtG88>~(Y^sF~VE;gu1p@mX0n zncJ#*^E^~93k|qxGxQ#@Gq6v~WvaBPokpc4RX(~Q^2{ndao0@-TkB?KOB9cfoPz}e zl`JdTZ>y@Go6^+t?l);+6FvOLv&kjoM>W;nO)QnKw+Q43TEW53Sdz|6Hm}Jt_ zb_nkeyH_!5`OEajrnb##jC(;$!)i?KoMa$99R}m<_i z@E@^_cwaKn;Kx&)q8QqL-aj2%J$`4Y@{W8pRxIe?^Q@U!jvaqejr&DcuM61m1mwT9 zkNOj;Gg^$R9en(@bT4Aid1mLZRye1WaDf;8bj@?7V>~2eNY+dhakv?!!}mqTZZg&G zQ&yz?pU)~2*>?O>_inwpf9Y5^PCe>- zaBnb(V;YBuZfxksgNJ4$Uo`5wJ637#lYe->36?}hfe%bZ_UK(+1C)<8>P;|rbc6hEx zwYu5EF>#@#RF>`8h}xr<=sN+|Eu1J^E$an+PwtV)sJq|#NMYLLZK^HLHMlG`05mw_syQfZ-W7Gb}tB&2BNuCGRgo@zS4XLRz5xhS1Op-`eWF`~la zp#R=i(raR#lL=gXS3kAcoBSN_VIQk)e4W(iMn-eiC2g**_u^Lv;^R*xPPn5!$xlp? zjWdz36m(G<_i5&zQCj$qLl)~~dU(*2#Qq;+ZxvNXvj*DY?(XjH?hxGF2@b(6I135x z?(PIafZ*=#lHeXRxa(Pvf6LkTKAe|~ma6)ys;hgf(6i^~d_t783&zu3@7+^|m6F$1 zf>5M)k$V9HVugu9N~Qljjtnd+O!O;Vm6VAGi6*9JlW7 zlkR*C^`?F3C-p~}#>=k|As!ImDtKFtQ!6*j0ZQUKAdomBReg65;>1X9`KsJx*WJ^h znA=^$e>635ib#gZZGnGz!7p1&X2MKGIufOZci_fo^U?nx@bRT9Rpdxi1Mql}>&96a zMwmhJ011gXtoLWU0iW#Ac4(1$*xboEA@*Vb|A5S6k5po0PyU{F_r+SlH>JZ^OtgJfm+2jGPQ%V252(l2fR1*Uv{<}kM z%s$`q<_O-DmU4+^ItCDRQ$S0zvKO%;Yi<0|%zhkuys7P$9(p`9S2FwL*IPDoIp-Ob zwqM~2=^s*-sZsxAu1abp<~o}yAo%9sL49>PrP6OOLkXgE@=!p8$Sceen^AX8bpmk4 zUl6J)J|XV?W~g4TG`Wm(EKyOF>vg)fAb?$;8m`3GLJgJLr7)%8$_AVz-QY6GTq)R2 z$M*WMJ;n-iJ_>%Qtbs>+#f~E2FRg#$~Yuw4NKRRP^?PrRqm;) zCM=p!Cd5(QUW^?x?4g|rF*}>NI7vS`DQXsH^;{renk)D<7{U$he%o__)n=4b>Fd`| zaHj>3GW#D{RS5Z?$N?VUN5O2lcG;48*mX5^%+>)i)hPtS&iGBIYIBekRm3u|EC|0s z9F)D82UrkHEw&$-Lr_KA$Dk0Rgfs1Ha#Rb3KC+}8AK8OJLyt&> zZgE5TDW53TMVto_G$`qk8+o#03g7KSbw$s-vA@vFTtoAl#TdNv;0$)>~XAu1#&hRextT8VcQ-G z&unm7^3NXqr%CqC7M54R>vAW0ukn0`Oqcn?+9_jpSaMenE9T=nB~#u@ z-vHy;pqMpWh5}dtirEd=Vg4Jy$h61~ z8}^a9PXJPZRap?KV3a){l)lEvW@_^E@2{*JwRUwX)9m{R3n()$_pNvPFD;x(Ai7G(qE=+4|9OSaBeUZPqR8dp`lUF&-*Vpls=>n{%gUT`I zk2!zKrlSZ>m@Xz!SAd9f|A%A52Xc(q&OO+2_A~G|-!+sERxDk~CRK1BH@@Q8@Zc?7 z%Vu>cCrug8yd{7SJq`YSa&3;g=+)>nKH;-nTgWsK{YU%2C1ikP2PgE&_#cds51Dt! zrXEVg*vcMV7H|~2Ao)jz$w(nuT6OiN!%l`zsI2KRK{>5*ffUhSK^@nRHkP`IGB^*) zvSOiFHb$drHbpW_6QU5y>n>MIPWUgzcn`!Fv#+Yt$vEK+fL2-0H>+&K7ADXtd({O& z_T$|u8wegBzlPnXw=N%ZPXjAs#rvR5mV{3m{b9c7>N9MGr$=8&!Jz;?p4{w-rPvR- zPX1KxeqI_t4po)hgI1!-HVDr&4VCpx8ECRcfZ}d$W4Ya7*ZfaYU@mwdq)2oj$2@hW zE~Ah+KeUzh=Aq@KD{zVCh3mgrsg<$Tpkt z?ALeM-yE*v56BM8MPL2>^dZ zTc0dCu40}D7tc^)D>~@Qe;~yHZ0~B96KVB4HH5mpO;!n8UZ52-m*$;0rK>JSG-f=zJx52V-+K{8J1^g#MQkm4glK0wSj zOZf&$SDat|U4!cd)ZnV48;X>b>+uivSIJ0tp`^tdX8WT$zTm_Wt^jB*ZHvj)^Ted+ zN@@mwhEJ62af9OU)Sp1l5S;DE#jI1o5y;ld#VdyblS@o^+N*wLXGw!k%;UwzmOWh^IEXGsTXKe8! zzof=+_0EqFlfm{hE*{`{_9Mc&P=ZJqlFWG@`y7FThxGhAhVR#YB2hB5nlf_QSAfk7a% zSl9&S{Bdi>avTNU7&r52`(Mmr|C!+>owqK_m6WO4KhRAkP4 zH8BM^*{`*QStD$VLSUIuI?I<#{IqFM0x)#$2Lw@7G`e(Yi>{<^dR;a+C1P2*ESqw2 zpkDXOiECV-Zh@}68A_Cr6L~kL9^Z{mZAd47%I(T&5=4RQdYMbw__?Jb@@fJqY0OXPJlvG(t z7xTvOR*fF{&r8C#E_hlS9q$uryDco%Z}@PMEk%w5bRXH}`M8a%sYL{Qf zUSO3UW>_|PjdO5|J1jm`qj|HG@zTDmQ(!eR116Lm6y20{m;uAvz8z~9H;U62=z)!Q z2+={@9#$ku`a#q!flR}9W)Qy5j5^Mz$;&q>3xQ^!8^MT<=Fo_cyTQL>8Px;&*FbJV z251{vm7`-Hl9lzTWBA=Vw*R7txg8zPCzF4w??cYduWzrOj*N(TxmEaGVJe<3*Qq+5 zg=TqP&#skDvg>buPdrf^bvC^A`~mdcbo%%{YWRbKK%Ku7|0NTFueSdo6M+8Pd`)yfa%2F-tPkqxNj}Q=Lo-1 zjOXxz|CX(u6})khz<2vs7;hXUu^~LAP_03!u*G883iI+?|{+S7evTZ7-+FKT;bdY`r|vLkpnHJ@(xQl zxf8rwPV>nG->hyVbH0i;4Vg5>fOGg5Y_VwY`mD^Q+K1^HF06gr+t+`G6!KkbzOc zGHP^05<`81`M%Q$zJn&B5*^iUH9#;Hh?W>qZeY zv3Y1IQ=qX-c^Nn>cjRI~s0T>z8A1J%DK~~fEDjhQIKLP8@6jFSY2O5# zK(OTQuhErtf%YF(PkDv!y|%G51W*AA^w~A8(uvUlCm5)MP7?!K34wzzMR*%D@Id36 zc^BA$VH(!dQ)xz+)Hrt%s8kllza0R|T8&aFfKb&SqgdJ75K!0OsWM;%?0;!hfp=gN z{oB$3%JuAlQ}^ywO=A%QGF?FSCX>J_)$a#kOXJx#pThejpaK{F8xWPsBJ>Y2_*PIw zPWla#5tRkbpuZ3nN~!_J-xgR6DS+wdfAgWh08e-C{}Vo+>o3*xR+aP!{q2ea?S#{x ziGi2S2oWZg>5LD^#sSBdg<;j$Ata{oKKy(J`ZppBSn|!D`nCn6{b1nV0#7poQAbBb z5tvkFQL*=`qSwGA=v|^>lE6H_!1Zq;4P2VQ@_#**z^=Ga{2esv13FvkcR_ln)U#=z z3z$jr@6-kCf?FrX{`#8gASDKL1_Fm>E&V?C#&}$R=RUqi?0xRf4XFO{mXbXFy>g&5 zK>2H41`T{;m5dnP+cGD0`8RF~+`;=7uM2Dym*8(VK&{>!u5V1&nf%|GtH}c*aU#iF zjj10MffiOlMKK^H3G7Jx_&Z+prVYe1OpW^vPxOBA;=#!Ow!})q#q)P8Rm%UgG)HgM zh=j{U`^Gu}ms}>+`!oXYs0aSHh0OlWSiNsd3j+t^Z~+UQT4{&)_o=t(CJm&xhQZ-d zk(@Cp6VD24Qt{BCC*Ju&cfxc1PC;X-~fwx7hnivak8dR|8 zJ~oo5ivc~-zI#F{FR`UiX0(iUin6;OS~HBsy>oUZ9&5n+6>q9e%9! zCpm}&#kL3UuD32&8@$tnGQq1P8@_1-44({D_+;yh3uPz>c7g#$p9gHDNx2L6<%g5Rp&KJ>O6Mo$)3T6KtP&HF-1eYFT zd9`CIJ>Q{OuvWTOpdou(1nEvaS)L_{EP5^x*Ks^fdjs(r(I+dNA?c3+4pH{%6e+S*P+LEt; z;MdVT-)O9HfYWZjFNBbX|Ky{<^Na*?Pj*_32xo3@=HlvXZfu8Wp6YiA2LoJG9H}`U zkcctgRtP5v3yG=$BCwEy$tT3Oh5eR%rJNny9N!ilC&ycp%<|^;mabMLz{d>hXBNTtTjpF72=&6d zu^^Gj($jV0IYz}9UT0;ttBf-JJ{Xa2*jP$>QapQ!I6W##5!VrS(g;dzV73XBTe`R~E9{aBQ(m6PK=GAjq`+a3qY|AuDye+su4=rx>|-faxU~$S@38+1Nq)H3jul z))agoo(%li;)F_w!okM=e~m8{g_?m10L&4ie<>F-%68h)fgOd*bk^-xZ zA%*3?ew6bKS213^&7#FJZ;*ZMsJ?QmxdlI2gZo?p74(C$vicdAmOKjTx!4DF5l9IL zWQcxn42ciw0;X)+B5er>12o3ttmE>ZsC>*;SA7mny{jt>wc2mz0qfU>oFpJTq6FVJ zxUFSR{p^Xyh6=C*lbZuJK~bv_j@>}6KpkU|^ie5yc%hrYJupCr5(CM_dMwQ$dBACW zL8aZKwdEakcjk0J)^0$=shMEl(q07y%2B!ic-P#Hpq#(3KT;A>&(_=qo|Ww{WmA6L zzr(mj#cH5n@h9xm0)S{279831f)|jlSo|Ucq487LgO3F737YZqa>CC0GLV!>mckIp zX0z%5nzX31F2#TtLBnucbUxYw`b!IhzBQP(DvT z2CZ(V)0aVp?T=S~ege93p^)$d%=UAAU)XG$PQ&60C1Y_Pe>!cy-rOQn%V+J}#ty5M zyj&K>mMY}3x&RhzUwK`?KN@a4_Mki z%4XtI(|5knKe&g-W=>8v3W*r`s`2yNdRd2#%h64?ZWF-!^d%@XRw!t)bLt=$=TPML zZzb-QGoB-S*dCM4}!jAbfT5CeIIr<_6S7Li_MYc$e^t;&mgC}`EuFe$Z zE&BV%wiv)`jKkKr7=E|-6pU_uEQ<&Z9Rj)}P$FCTU5y5Pt&F!mvn5-%aG}DxoVud4 z;(7l3(BM!Xv5+)_3r{OLw4^ZPr|az1RMaelRbU$qGd6QQ3>i6J1XDrlFT-O7uSmgu z(1KVTs)6uxlfX2J6BPD-pYtSbIztrtemtQ6vl(!wdQ^BlA2T;G5A`XiKJtg0*TBui zn93f7Z!DF`1qUL>eOgGmWSV3qQzk<~_6|d{>~qod425+I22HRm>Ws7X*B=T?wB~Zn zsyRu_*>OZNvBlJ?YA(6IH^*VeqsJA-6Bb7a%wss^u!g zdzhZ&E=zyfkmL>>T@ie%KkkF?u<7pcSbqUfL}l-5(_EWRx-}i~wxT~Jv7^})Oue`n zlgVrA-my^4fKprQC{Zb?DS1rj8ECEM(9fVzNPMC_b+k@Tvfa*J8+nAeoF`F z$#a+mHJtRz2LI>-f0m$$ur0X_we4kE>6GnM8QpcucVoRSMl{H|E>q&-TG(AE##2Sq2^j|ou{~Pi zQxY#SMk2gsy~BIJZ@V_VHoX#hAbkJ?JiI&zJ=l9icO?s2}yohCSG#ya(;9#T~!^gToWT zV2s zYunD|GbSJc&Uof{R_f{}%iC=0g`NxDVz``an?VW2035HvWJ1m!D@%YgewT0BzI-h+ zIDg8mbPN6VIWC^l6=h!6gVa_4ui9vU*(>8sl)hd`9hjmXxjTpiWA@|FLPs2Zl6b!; z#P8s1U3$O3T1i3UU$}jsp-GTCLM5#N8HPfSlpzO=i6F$_#zH^A1ll-)+xIGz1?Zh& zLi8Fmf!8a8ke=Z+bb~iR-x`DZfFpi~6*DGf2y}!gY?Ov#2#^l*FaC}IND;@V^iMwH zl<1`k3z+|owIBj(CdN=%2w*?zhN<2lDA}?%i~E4<{1FWHcEeD<*LMoRf`Ud0Qk#YF zb{kY63^y(OvsEn8ewdC2%vv|H2TtrquHPS-i24NtLhd~X;J>3NZO8}&mu^aVgoQWZ zMxG&HnZo9LpmrT_(T=d20zfVo(9iXz?uVRs5HaULH}q1pg{6K+7(Hh*6jicC4t50N z|0q@2C42lOTP2*XEkffA{Ru&76Ze8950BFWv3eV^av)PXsPT-;E1x@}te;;y(*2xh zZ4g>H!r(jo=iZYu0>cgQ+T@}*J2U=8(a#A66v@X_-b027k~h-~%YaGiAy8+OS{bNe z3Y{GkUip|f+XQjvVU+}_n0TK>F&!FSML20vUQxvawH*#xGD~SzT2jkl-bFGUobjbg z4sYfJxuU3~#L*qN@!zr;vl=_t8Ap!_r7rN>cdb7!zgbqb=N8=J33@r8w*Tz@2qAif z2B88KM2oY^l4dL!wg!-)@H%au+^0B%RYA|Lt3J}-Gtw6J`MD=V7CT~k(Ih~sG@^F# zLx6m8#O0!`jf8nbuG_u)wi~%Swp*!t5=R6Y6cP$mg^aY2o_Q1_ovwPs=Axx-(|s$& zD3afg{UynLSJ2Z)C=Pj-{GRwe)rTQ>sB>5CUS24bc}H%qHW9E@#HW?@b%N6Y!n|NC zDY#aZYebQkhI+SPB`LKd&nGDtPFa*rBDg)?u!&n%LsLUt<2t#bq(gIF15rb5eumLC z%)VUjV1ZA)aoWy}pRi>4$iWqQb=qMuRejDu*NIM)^0_5>;Azdu0ik~iB11ZnCWUGi zBSUu9if=qGodXcLWyLj~?~x&QX(dFdY_j3JfyD?@^pGuIV5Tb}JZ+*YCOoUED>-Tn zSyiMFKp*fmz$PFwAgK#cSHZ@Lv8wR;M*!Ch)slRt2kM%(Ll*a1g4G|PH#0&@O3?cxgay5> zUt(rh`4p-5DY6S@T|*{jc=?F4w#Uybyz1I`92&R>BX56KELFr*d_63GSQBvQNEOND z?Lq>FM`EirGqFe&)T~_m&bg}qsWz>?#gVn3&ZWVVeNxmppAFt@=df3PIp%qy?{3J$ zoUJv{Ibj3Xi@sd&+{18L<0sCFouDplsvZKlD}n+Q&HaN0gQI_zg_b801PX6W!dMh^ z6$i@3M@foq_F0yX1R{>R#|EUPi1(ODeGLIrDa7GybH6q4KgN*4juenw6g!!eH1_#lU z1Z<#(2M0MG1#%jtcm5-o{7!W<-_MN<{YV=Z!f&J3O+wroAuD0{F6j0n<4wGc8z}a} zRZX0s&iMADe|VynFS%FZ`Oh0y(pw$1USe9E+}r)V9hFY{+nbSZcl}m~sYDrc<$KpJ zLF6L=2OcEIJy&U<>?Tw%0nnEyL=ow%@UKI?9z3xd@dOiv9vrcoFk=ymEd0N_veF_4 zFL;P1y-7V>16dVneI$PkPsdcrB~TEB2-ce8t94W8TP^q#lCPj265b%nS2 zV>_c!n+lChM*7Gx{ib|kXWlh$%hEcNHSGTi@I(@Y~2|&*6Oc zp5H-3L0xTaVA)OUIs2rf^@ym2`t)q~$0+t3(Ynf`hcNL*kWU!$C92TK;9b*6vGZ1=OIpq#`X(1)?*0vdGB_-+B_K&|h8gl#zJ^ekX5OG27IbbKR)YgP_No_NCeM`I46_s3kxUHlm~uv zVT;O)CXvutk`k_A60J?m6{cVk`HSjvxbIdR50zrN097ZgZA7~2nS2&{Y9FSP_zLQ6 zANje20OsT-Z<~MW8Qe<%V3V^AR#ucOXe5uVLY_{&Ud2v>AG2gB)AbCxoyD{xf!P z4fo9;C=U$uwlYBoISYZ5DMU=KbkqPW4=i=02@hteDZxa)g!}+y6M@#Y*9ybMwnG!) z?UtVk81k0NI>7S0fF`KigV15y0N@iAdyd=D!+qDi&Lujm8rf;4o33J!viR(luJ=3n z-V9Vn8Y}*Txs!@$N>Z`8r;dtd^1PXwj@tK1#-pK@+MG&e{GpHz8T?VI+HzZ}%u%eK zWYXGVTS~oAhCc(!4J=ZZF+Ud@m}@O_ey%dG{JD(yxp38tds(_}`Iyyv zT&QlHfCYM-)a4fetJFBF%Ssjt^*F7|QWmS_IIqi^J`46ZrORSbn)IJUdKWBv zHo5=2eNyOlijG5COwtmM5+YpsFrIBqbqh0A0tW3%+|+{2xVAcf zU!h^0WO_nAU%6DfETYQFZMsxw*N9Lh}rkyGh?ooJ2t;@Zk>yE)N8c^tTa%qQ8YoXAdf#y ztxTooKZ{ugGv(F0=DvvPl>rli!zlv4<{H>-i*Pw`$kO5;9Cx#9sash*A>f`Ici(G) zJP~m3(A#HnNRW0TyAKp4% z<=EKDzmk2z=HA>281U4M>j<>UxOnvI{L%~umI4OVP)`ICNQ>n1QoF~xyGWQAo# zWQA&lYlRu6oLdH{pt~;T%U7&WJN)q=pRHm!&+BIBTmG&5=#bt`d{w=1&dyCrLyp`U zL6BOvv(8Hv-I{K52BG4_0r5MO*ulAG;5;FpQp1DpbKWx(KvU~$CPymPjH<3^4Rn?G z!g~G-cO~kA^j(*-O&X^@SyBCu_=d9}Cz2M}vp{{G9#@_o1|Eq930VxEe32y?@B1nV zIcQHAK3N1;zvUKF4e`s@hK?WKL=OZvg8VgFzs-Mu=+eBvEL>u2kL)DBTG;a*D`O?d} z)J1LBVETv2%b&;!ZXB#`ih=Dz$u9;jxiM8Wla%z`lDSG2dWCda?yp6Ot|_Ox`E7JE zGjfKBYbW-&1I@!1nm9toU>!D z?BZJJ2hN|uY)o-Qqr;zUCMWRM^nF54+w)Gp%8@k9S?*0%s}nfPKPl|)eD`7%EFKnQ_B80<0{ysjhJ-i3 zS2#hep zD%^N)W3-4?IGq|>O|Bu_+SRwmXx7hkO)gX(E|4A#V1oDNEnq>_RjL{p$9W+bO6hs4 zY<H+bA)c-&TSmJz6vJDLtaTa0HVE%5Y9I7hZ=QU^#BE@`+or{%#B__lG6t zjSdAk3Nde~8X}^tBHgrwPTayDH(p*l`A)X(|GfEmuXnx@a)tj%)-Enx`!L8Sr=V5a zNY8bA^*$>?U8QFU(aTWkRim@(^;f6FI4xLbbg9<&-)6Fdm6p?BeA0tXr?h+u?)y>_ zGEH1RKQLqjazmeq6cU&nQ7bE^CSs9@(!sPP$`BAi_IvYsLJ;jCU49%Pl(k;gj{k8?Nxc)|B>_;?=40(Yb08{qGmf|lTC?>vMMs=d6? zC2GqZ;g*<~nQ1;9%L5%Ru3s9*UZm8ybASXw0#to$fy4S+!*ePRO2cCJ>DEo?r`{L4 zT3S4pu{_o^Q=tVTiQ+5Exk0Y6bNY%BfcMb7dsy)I-p+xj%(fhN>>7_1Eu>-6r zgXAxlO@X&(q(HNpen0gcLD>Ol6AgmxjGCv!nU@N6f3nV(gC z#nw~!A-b_d)+j=b0Yc1OVA8uRq__eT~(7+EQu(I1+7tR0abUyzH5v! zKQf7r=nRTEBr7C13O9)al}R%D|;{)1m5njCfb3Hd803fgwC|f<~14OvwB4T9x0QmBNxRA2wgbxuZ z9}MoO$-IqqH5Ald)0c#2Dk8WJGStWNWD3a>~;cmF+ZkS}D&@ZJMQWkapi4 zDjWQs@-DO`q62;p003naL%Kutg7%fSPvmY!X%_YSz?8^)g(A4)H(q|n^DuWN*vsjP z!CB~Z91`DZoEkXgP;&(vwGcru^kU#BOL`)go9w6M<$l??aZ1?r(qawbYav^(YK0-p z4)I+@!6HVX?Ae!@0_lcm|6uLse6zcfl((J$R`idPHB5VJO+bd2^Y@y3L%2I%LnVVM zJq(Z3S>x&&9Y%}9=`PeL6I#mbL~9-?L}PO+nh6hcI0!X<2wu7%8Us7=-7I@5Exn45 zp1;=_=4*>v?7}^H1JKUXvQ*6;HuK1^&%)0Urq+qoYuOBb9-wCXDU=e5go;gxD&9{Z zjbQBUU?>;~eFYRd2W>DJnaa@(>*xuDTr}X3*!UM1?urq4KYmw4aj4){it7i>vl79T zSLtLMLQ(!k$?2966K$y)q)L+%JxHTCK{Ja%3qFTAub`|-9FmbRSBXqMS+kgz=`7Sx z!ieR;ksZ0DL|=&I^` zOwlf^ev#qMzoUpUdv=E9ii~0FOa)hx{AV3*M0IZ*TPAF#hNoYhY=n&Sp4lf2sHD23 zW&&FUk;46<yl+WF`699lRBWHOr1wCQ3#qNKvjyo21N@l&U#(dSLM0vF-Np=Wr;0UMu^>EJJSKP}WI5W?f@QM$+fk|@5O*+rOa-d9@THW@G(EoT;G?Hg z(%2_72iSJtx~5~|l4_))QJISk3`L3d;(+-AU}dE&n5)WQ#*cJ^n5OR2!6aM8YAJiI zN<>E3Is}xpiKTr*I~qr)Qt% z5wi&z`-hkW8)|eAj)+q~Fz!YuTB(PufN8px2z|9?^T9k5b`emsH@>HRp|ZIK{;y~q z5S!$6mTfMRGocg&{-@}(7_2CgH3+l0N?6UrL*)tR&1SS04+4u$859CDZhn`zMbbp( z7^E!#*}{Z_B~Y9z5jD&_h8*;3`fv*Cg`Q;fLqX_$bl;H07RxIGYmWn!GQfnrdrgoq zTTI#t7B)W>VZV8-N>D3$KUbQol2o1w5ILFu`H_7^e_+m_>IOzB%CK~q%1fS#{Peo% z=wW35_3Qj|N*yjK(Z>DJX_X22h4HH!*VfL^Z^=NTJ>p)+XIN1IN02%TCFqlyi#)tHOI)iTygm{i7W=}qmUCm7GaFH04(xgS52w(lBXzCNQ--G!-c1JG@6 zy!(5q8Y6>|kGZ;yX1{bAO5hAeP7c?@Eosu%Kt1&lv#|7OPVZcwNuuY~FM@DvxQX(L zD(7u3&=D>6JVtH$BKW&CX;|67vVymqb$mN{-s)hgg{KiYy$&OC{v%xA>s78z_wr-- z1o{W@M!ufIcD}d&g4V3MzJ*m`KR{`CunAE|rS$NTvL%)%pBklk6zYlBlX%rVJ;=i3 zh1U;!af-eP^u7S(^!&H!T*o(XxJ@{MCNr4+bvfhCp3R1FXm8BU@tCgH&|+a{oD&8l z_3EXwgyMm-yn$06b4YG7K|INiDH|0Z*1-}B_?MMpIB%n(-RpiISSg(v-vD}K4ro7Y zq;Mj3_|O!>*-XS{A>T<&be<_?y>5&fx`VEF%x?C414Am)97S{Xo#;FbIJ+#1$za;^ zO@;O*dWbJ)<2f8e!NbQt5|9ryg05{F(2(Xy`)D3wR#0r|T8W==p7=}kNiEyxY?#X4 ztMYNf_{RRF*TUkeV*y~AVFAI#(b7qTz?C^Y(<#8GT-I&;8y+C9n}yEAL*JzJ z7qfFgXNNNf6*V)}hFRWC{J5p9uQ*@GL|jbR*DVC^oX!;-7!GG)vp+}~Ph)#nzQ>Gy zTW+oG$B+VGS-*^M45d)#LQ?1V{WkqQL=Gd}20N*U;C#qaVq(KhbFcy6%mV{kMw0p} z7~y?OETm5OMkI~uvD?rw+=M&GNXJ%~1W1Nf-(d@8M${)9o7mBi8YS_Pq{l`M$P&vF z)8q-Pzb7=US49fsY!?h}W8ps)OsP*wh>K!mA$MTy2*GWA{EC6FAcv@+N`ew8fmbY2 zMFA-xYDM7`cJEPFAc6^qax|Tr$NDmAlQ~Zu8w`HJLh!ANZlX)0T&XJh3+24|A1ScU zGNK3ZR}yT}kOX=sB*vsfSXxfRXtFl$5PHCmRjSGbezibEeNowT5R+kn`RH9LcwLL^ zS6#=`8CIwQ6MN0p+}w>sApt*1@+Z-2OZF@r(p2wCE1209G=JnOH3K^ z&F71#SbkD0Z~l=kVu+-G)x8zH?AIhJ5%GD&Pw*Igux z6VJt7Cu^he6&t|ySY^EEbJ*s#&|WT0QkGtP9WhE4-nJ`d_Y=dG3le^E`+&WP|cnz zecSrbzP$a+_l$Cj)7U>h?smB<=I-_(lTVnBTWHb;_{I37qDHAi>3-F4`ET%J+Zc;a zK@}K?N1J9%nx=_V?ct9seiaK`a@k*n%RBOJ=AYFC^N3UqFc`x{(MffRtU|+UnBLHd!^2nVj^o*EilB8|;j#LEdb2OD&OGoP#)HZSZCil>-3C{_XYMz*0 zem?QO$i3j5?ubWoCX)S%NU({!?+$5DAkQK}V@$dHstgg2<&Re7j~xeU<%}6diqd$a z1SQ_R60KAkEmY@r>o6j@*vCPnGwExf# z#)K6KdAHy8IrW5IBJh$h?`z@pxPn5nq-@=qe%tdSgmZ;Vq9%9a?F!ajWlq*Q z4`IZ2^E*J`bL)+}3Vci4dfLsF?p(xD{5a`DALYwnn=p!&c}x3I-$|Eo=U1Ii6*lP0 z8Jc%mJDQJxw4->#YBx?Z9ZrJYAxW+9m)~9*k>8VtsG90~OY*o|8<)vj7H#X)sMO4- z=nF$oGtjtxRVGx8H(2~x+}N>m4`6wvBVhqpg(U$xlhyr-9$tq1MR?brLHf;z7zoF` z*W0bu9-a0}W5}%UMo8BpV-Sr*FV2$53-(jNOh$(+ahWhsX;vfDr!B8RB@unuHCyg4i>*&>BDU9gzMLf=<%u5msr#Nj6=!sKa78ZBWJpq4i;dDJFx<-+a1)}Yi zyF1q*{s_V@C3YVQ-0#bMGrWxyb8xG653M#j(0VN3w|PK&mWlO7`=)}f>gsqmDsbsF z9#7*Y{3kVhy+s@r18!LQW)?$dj{x@AQ8^EQFVstis**(Rw-m*KfSF(3)GZcQOD9*8 zFHeWoO_zrlt?|H<6J@=xJ|Yqo9A33If6T%_{{_As}N(5+rrpJTArD*4(YHN8igvzkfT$U(9;=ZlSUMP zH@`SSpFAL*Mm)z(XJhayvc(emg_0MM?>CO<~1ml3s!+)0e?bl}P?J19=h2UhHYGaQdn^ zz_iaeUFYAe+C>tvu%qYUuAzux#tjN0Mrv!C1t`h`KM#3oKK#ThfqUW@<~+*~l#VjT zrpgFm3eC0ZM%k?HztmN~bGV8LXewn=25Bl!n&j#LDQr&KV=w0K%j!61C$=@f}pmlBfC4vedMvucH0H?b)b{bGjfn6BGscm8+{AweBo6wz);f<_}#qX z*Uo4|HhS{GPzTY{Ni=Sd7B2w?md|~ND={Ip_z)1aIdJmV_Yj6iMHrmclG!z`vf!{> zxZQalA<8%+<}5Dk^D&_sI1}^1VaKJZa6?LxP3J6+Nf9zbb48+{T8iLNxLJq}<^|HO=Q-66do=rqg?%vD{#hX9gINNoW zB#{m`0mbYJVOc+0S7(t0lm7I&uMx=hX(Lb#>C@Ac{fv9^P3$2^6Tr#))KbtpMYxq+ zNpsa3Y9Ynm=Xx6%tD~;`iho4o6aIQewwJ|y$I6x9dYr+raJ=41O^NxrO43qb$6U|Uz|z8Op$dh1W^(>kvbtprUeo3YHlKK`c21xz=q0+|(4+}os2b2I}~bKjVU zHbY-N3^2mw$fr(-@((_jMCy#%8b9DdqmL=xPvdNM2T7{BnL%~So)CW7 zC>nhd4l_t=0)qiWKt^^jdK7IapYxX(SkRtgGA1apurE&~H@2=XBXsNRhHp^OGb#x* zmfZ^bXjwa=@8PaFxEU?TE+zk<*O`$`sqEEGq2vWk)Fw5j2{ru)^Rv%2LX8CK(_UT- zDWqoxLY#;!Ylt(X5{z9CY-n_JRAL$%7Y+efx(M$8ZdN$}mL0=wWo{}RZ`rrA-iI}D z!m560J9cf)GuL$2FQCP< z1d%RLrn~x0__I~R5V_0pWxoS1UDLYu)|K~)VoS)^#QB+AU_!#^+R0hP>C$EkJxg7q zFcmVa`*|ne#lSQ8*nrIqviN!Dtf9tZUvstSzw?!sBQVrPPUM@n{I#wv zkbp4Z?#2suPu@vEn+IPc=KjgiqR^tMnO4=BB;NtRIvW%T90t|4s>0|VwkuUY1*rZeJFVrd^GWtq5%9GnwIjO(w^5gM$661&S zy9+fW0HnEUNisp2cUcF)slNA1EBj=nPx)4KJtJlE<4sDH!;Gq4Np)H!$B~;X$yXgdm0tRitc%pr%tXh=AXJljh9==J-S$=@0u=?PDKS5}k4k9kpqQd;YD) zY3T$xuBCF_p^KiHMP`wjpTP>{X}mz(QPdX7NU}hw7b<4C#S&IQDrJAI$^2KVV6*5? zgn(wz=59^v^-ugZuRV+VTm^l~4($;afumWqu;vnF0J%6M7P34Sk@1iEO6dqaRwW?f zFT!i`BnKM+yw-~4LH!R`)7jblryJrvfQ@DNpxB8<#2Z7NKy&q{HWVd3B;VUrQXUcU zBarOH@9BO8jqzH6#q1ltH4Jx7@dwW96M*9e_sdsD;h`jRmh^#KUbxlZbY}jDRXKLK z`r>1old8(4G@J+4o00%S6YZhO&(%XdV=_eqa;yXr2JM;Nxl2laxPCfHrIDX~gWpjZ zox#dSuGK_83FO19`7rosRsmHr_fQk=UOscNEBEP-Rp@h8_74{wj?-?EpI&hbrni9O zvoHbMJUfDk?{;FWU$|yMk6;Yz&6FyzVl>2>K$L5U0%=UhiD`XiHhZ|aeodF`IipR( zxC*QAPn1bpdCs7>>Q21=*}s^$M<`~0K6I4Y`zWmH_M%Z#v&DEnGm*}~zJ+{4(D8EF z{6hvitpP8b=`$JUT5vSWAHH9Z_+yWN$CC6H4L`KO@7o`_(I{ZyWXApvXKxu7N7JqS zBEcPkJA@DjGPt{2a0|iRA-Fc~PH=a3cMTBS-JRg>aL9e{=RESh`|SNY^J%K9x_ZsE zuI?G=UiGJHNIIt-L}yl~F^ZkaXXb1R(W598@J$GG>EUEg<+dcBrv57G<&km(FGfI0 zD;PBN{n8d*9XlLX3oRl0@TRogSV49hRw-?LHzYZJ31oc?>b{fRn zpw8)4P=&kUGA5*oj#5euAZ$bR7~Vv@ATJr-x7?>ccZebZ=GPkJ+cov-@fgFkhGQcm_UmxQd4%q{J`Nb1PQw;R93KZzqFU;YTknw-; z-|BrVASd3Ln=A~o%B%2sA8ZScl={K4?;Jo!tFM=^P3a&LSn3Cr{^nA5osNJ(GN;Ih`RZO`7`jpJFe@?t9s7+qe zBTWbfMcbXX)X;&G+6k@t8zLGAob??%s%W`wvBEK}W)Oy_(74UONsxH!Y2^h{{pBUavdfB1dSK<+AqulV?c zH{;XF0^rw?65*j%#W9>{+N3*HtgV_^<}+>vZ4~xSsT%jvR`CElXSr}LML3^jifx0- z`4Hf0ly5~#Op@@6ro~GBk}zd}{aW@&y0&$)_sE!A;$co1_fD$&kmdAF3&r~KXAg`A z06TYY)?;jGnoCg9^<9AEJ$mrBjSp}dBnFOh9|0JhB%>1Kb7Vs=%3>Zy7hWn6g>4xp zl0XFsDl<$)mk6INoUW1E@gFU`GWXK%_hab}JioD^4ur^Cqid|v{K8@}Juw3R2M#B$_;yL+Ju{~8Run5&57+g^r` zJv{QYR5jT>-V7x)Sf762x`7LsXw~^T%SgYiz?951_1Yb4a`)q}c@F z>;c}Q^JAZ+S|eD7p(A$0Q2)ri-p?b{BLRrRWuDf zw&WM}OkvzRGXeICSXAz*UcF#ns%*58{IMm2FBH$<%Q-fJsbA07IlLFQl8_*EzsdI~ z((H<Dj0raCX0r#% zy9%k!DAuJ*{OwA`E2z~>?_#|zLP_|Jos1u!(5&shi+VqDXba^2pmQiv!HF7*GA4nv zk3Ow`bllE*)XiO6A&!={l@0!3^h5M;pEKbKa8Cd%6z4GePd&yw$2`A09o_bH#2WLx zlDyq+_~5wN8}Te2w4elEYW^-um|qm27C3;1aQF&X92AE$GArde{E%n;xF~}kh6z)T zI6kQ?K>a(H1oJ_xM38?<$<*H;KC77gX4GTU8jI#W-L1lU(|F~QXYUdz&qqK>LUYJs z^#QgpLj+#s{Y9Q~J$G<2l8Mm5d!_d*g%3W3St6%F!NR0T;&N$zx@|YD>9loo!9QK#4F>70ThvfNE4OAt4d!Rv`66#kkp-tfddgNAQf1_|P z9KliKp#`<_z@f0n`-u}3qbRuWvb^)g`=EH|elKOie(P`#85^wvL%BZPe4wa}6u2VM z@xs7P1YyZwp&iys>)1Np1kGTju6D!F&W;jAztNRQmtaPgR+fkMbXaDflKi11X;Sye z{h;8|=H8ru5`ye!GvKobf<- zrMCE;rMud?wA1w(cgl+M757N>Af-B$v}>%b0K-O1#kO{E$IgZXVC9ghzIvpcsJ?%0 z2oEE_{)=V?8>fvJ>DUGHKXYA8P|0=fCK9W;Wo(OIyVE>S``s)g0sE25U{J83G2}Azgnr(ZH+wJvTp;YRiRYn)_>fe^gA@IWy(kM} zQFqpdk5CgO{lVEQOgVV`_<-j0&TcWHs1&=ITD}hX)@~|1P|h^_d0u&kv=Xvbf2hyP zS<40L`c{bP=F4YGsKCYxLIW>0jhA=rhZufC#3NT4ts3-nG%gUb5x7Od7av4|9x&ED zS=p@dSoJpB-vqymeplWYjIB?LJv_tDmpn;h!uUf45d4ZtbzvwKVpS=`% zy4jv-q4W!8e1XEq(9EuMa@XGZy9?h?408x*)~~9Ru#Tg{_dION^D=lLWsp!$L)x+g zvT|@vkHuw|nF4!TN!zK-Fe7>rr}f)rMM}LWc{&u36cuA8dNN_bdhVj)>=i}%KJ(X6 z)^@*ClzW!eh2zvjp}Wl}>9>LS(sQzI*LL8ZGJ>l|TgT z`#bGjn>hTIFNs$?C9@EMtA#qV_FF7y@&n81Vi5IZ8e_;AW@qY>W)wAgw}$5^05@5M zZ-bw_bX@eZ!hjCmB(XBlwaADtiwtI7|YmKBjw`jhH)12|f0yH0a zTgcpEwN)7UQT(2_Q^9hTtV?H8N9PyVqqYePzk8_x+PV-9LCi{0>;Q>mtMHdFQwV8x zWStRV=#bqwnh0e%{gatM3g$hDy^SVPjppYUwF6|VzSVxc(~+%y>ln6|DYrZc3t|tH zC8=28b>J%g+==O()&YtQo4~Z6>MMZxbMQ9Q-R;Md7xS7Y-t(v%r!=28t6P26 zsjK6=o6H36F}C&)&)s{8t>^)b^PcdI$kdS6`iU1uRO0aTtBkNoOz67N23brGjct_t zJk96}4Bs!OU>a>uNdDWyxtS!$%1iMXeRxvpoV;2vdQ5Qh- z_irw$3}K%!26F{Jp9nvX_eA`*<>%5X?3D4YnaMiU<+_H=qqF%c66rUZ(7`VQrl?DW zoSwHY)5}gPXMn`K!!j)U0X|=Xp~w)MBPcO4z!^@xY)qH0Y=YvVkr>AN1T1 z45_;2eo5`3m=KAo{CtZpkDEwM`SJkJ>lD6xqvLTjaeo@m`mCBsmf;uD8vR0~gs2{? zRlV8hLfas8*Iuc82W2O1;GmkR{sSeS&`Xt9HVs;5midx-zQ23Bcd?lztGU@mJY2n0 zAr9)KcR)oSO+p198{SwhY~zCUQ(@=jyTdkuu`ku{4^8=F_p6{*hzI5J$fXZgeqPfCqgAck&4sWf;4%KT>{aWrTsn$s|o#)XV z`>p9*$4}rR->ECfs+8vpg_>}m?r>7edwItJ4(mDa>+o%;)oQKf#MSiGXcy9F-{F_5 zmtigi`AuY_QL5<%=_(UY^|!;}k34j%gM-S)pB7SK@$fWU%rQqu7f(j*0Y~T~Z!4>J z1*4NMqRZ?)ul>$-eWJFS8%>vLr(sU5m!3yuME$x-mkdsZAI;n zA9N>8HRfBWMZdrD?(xpe@&If1qfT097;nFvQqC4cjwcway|K z@bm;nS5!Mw&?nbCZ_Jpu{U2P{J7&peo4%&ZI^NMLol2kaO$FKF0pRz>HtKXwBAb#V zy%fe^!B75(jm>4|!e0>rX{n(v9I{m3gXfIbDD4MUb;Xx<2EhzY4Mg!Jf1DW8*>mg9 z@Mpz&6{ts*r$glXsV|`_C3@rbG4qsyF`#@tp7;&{ptK_L+7n?@LZv`4BVlIacv&J_ zF7P)L$$_2AV)&_3_yKH>k11lhC`^I?!_tl;)Tg7IbTda`uOd0q<2yU@)xp(gj2`VJ z_vghr58b$a1Cpd>JNv7=E$we^r;FZWYwYgHgOuP!eBwWu?LKMX4d0^dpvy1Vq<^hD z?A^l6BaeT8>Qp_JxQ*{%;#T;i_LERZdo7SFK}fEO=K-}U$Qc-N;tL_?B?^tDw^dv= zJh}arrr$nO)v+bsKSZdy^g2#7*;9zb1p9WanE}Z(_%n&isVRrSXXk>9a$5pCH$$n$ z9G1BKg5-Kxm*ODpk)D@Tv1s9IR1!Sm#9`q+S8>@=b$u|~*8YgSWdzQz1oIsXQ-u=b zhQPlUp2-pg@ec3^Lxgzm(7XA~%`Hp@;~RI($4V0j8Xa9F5j$KuXm_r0_uuuqLu0q~ zWvE^T?o8v{c|7`u7091jb3%JAcBTn|U{HOIDobsd(Zia^W(>J-(KUUHP68FOt zGqNnf2UCC~CwDyR58C3eF zm~c9FFCwMn2s(mwwCI7DhT$x!8g-Ot)_9J=C*f$^cwt*i`nd4IXjXCkTx9@L{R3L{ z2YK%=BDS#IF_0?lcEEH|#({^+kF?N>B2DOjV6)e@iy#UP_-4{$_h)bm(P zkgEWgsR$nedc^}XPuBpQs1r@9fnAP{m$+Q10?yV<8=iGhdkb0SDC zU)Zsn^^6$^FTJiO?*rc@=Li=Y33@D1Wq9L3H3TQ{jBD zYdR8Ez+`@smh3ruw?HS~)DdHtN~u&$%@u$`I?G|!%NILU{owf<^SHn@++CTgAP`Q0 zQ%(QT23);*P5s9i`wm$MYFHfwjlinGAz8eLOCb)sY%=?dB~r+H#IaVfxY zf@}Kt!O_mmivHR1TI3k&+3@1SGt*nWn21)U`ET6kRu|sect@Gn97mzo5|z2jgtqYgDqVQJ)Kr0!X6Of8W- z0}Ar2Bjvh9C~C}IT6$|e2tkICj5Gkg9wS;ny&kw#>@S}r>AvAGLp(8YnFh0(jLS!* zCpb@7MEbddCC>ppE=|lGLGV~~I|F43_#>V}ElFTQwB*+5c9lQi^2Ba)^JQQQ z-erI<25SnPDy|oa43{#BKbJ{koGn-0ZF)hW$)_B4F7NPWX>`dWAvEFh1V|T^-sn>{ ziUg*7F}q+N+R^4DuL1TWfdD$qbOFhdP!Gg%o`q13K)?oRdKEpo3FmFB8gQkTlndZaX2R2HvSm{ZE-A0^SxdDU~Poz5V0A9NM!`(0j zOL(2ibXL_lq@b^uKWgDR$RbFNX7#56K5>0AM}o7WvDrh_)>om99hda?$5v8TezFJNDbGULAd*#!VaysSHjXE@Gie+Z~U0M z9uWmGL1VCM4K2RP~|P4KW$oyz4}pjT+!Kp`s31Un=#*pWLYFZudtWu4nE5lF0n*zilM(#qqU5xE5F}|< z?%N*%@8YPuO{>ZTA=5b5VJ3^kwE(x(mPpj$b>h{uw!LMy_M4;I2t;DqeYB$_Vw`2B z#Ie#GD2)AgF_VuwP_U&gBL2R<_huE@`1Aa#)H^oF@9?*@q8xcUh|+f=Dln&J-D_A@s3OtCBlU& zXM&%R)`pron8nzM61Q2a(3+`n$&66(5WaHg9Bl9vD}R z(5&l`C&Ly1BSA}6PHCqGdRcMG14@+Rf}EvWwel&x#ME?tTQ1&-@UwzvAtd3_VpUf% z6^hAcUy1_bm*-ARsw}2p9`v8-;YqP4RX5{xQi|Ph+S9!mGQ%4+Fqf84^Upu+WOXAS zd*C*3&y82sB4ockc_!%-e$_bh{wR_2gkUju+oqljd=|?SwKHfrN!Xg~6Hhye5t_^v zxDQPoZ*SJNjzPEZjJt{JL60(3psG`#In0wBRF|imI=D_S&y}wC`Z-B5WLSL_EuHi! zZ}N9|tUjKe@x;fX=x-|A-61^+q>6@t(?eehC1NuM;QNYkJTz1Wr5Srt*d6Lpr)RXp zRT(J30Hx}VH0GqVQ6a)ZvPvHK`VT%O$WJY<1tb|b;`B(D(d z<8G5Zja3~-+KL|I$dE$&qTE|autJ-_eYZRh?o^pgG_nX+;qIv-a({5i+&$*cp!JX# z+@2zh(sJo*vMlTZR#N-Q%NXJ5zuh3W286os7)B)oc`}=2zxV6d=Jnrr9aP@%y?84_ zbmOR+Q9rP6)Mb6(+D{B$t>qV@qBIZ>noyt;Fq1XOk)CpHQa=4bX%L#=lmCA3eNtuv z|D)D^dH|wz^nJ37H5B`r>353p^{d7&p91e{_{(?S=XAFId`E?x5eGwouhtp%A_u(B z%0{OyceIyI*g!`~Jj%~nIT+V~JjKdVWinB`$AjdiA>a8vTLCr_+Y0uK(71Q}y#x`w zz5j%MAcs+!NPmV=C53OnTda`MHBC?tr6xNyc1~|&P9jOw9W9q@SfnJuHLFp~F!n^K z!JI{gbr4!Jb4{e#kP}6HMv6&G9}c*2N_z5op}g>a5=xIDzrGjze9ghw^gp zwVCjBEuL&(X2H2$woaj7KRme*&NYv_h+J|U-D!EkE4D45WLr0qm5gz zHabImVVxGgzp}5DpE9Y~+>+#x*^`d@>Fk$Xq18u}?ny>1=?jAFNd{B>?$ ze-VBMm~I;$<45MGnmq*|QEDruKCl!kR9$>&;Ip&mG#21<0ReS7r&+%>^tks^K_@E0ZaD>m^-qyGu{IYLWh@F$2{AMu170<7(09AE2Swbua32g z?Xp58Jj?wnhOyk+?Rz>ok%KkW$g&WwkWs9zq_+dN8~teZFei~Xj-b9q z_vwc%QXLwky@-wN;~uqq)1H&PPBe1KvpH5i%9pFY;&~yMQhYFW1ePJO%{UH0ERL$!Bh&r`j}x^2k6$ zyWx0pkxtiNJJ`I_m{ZNPLBBYfOk+z;Eufm;kdK?7DWgHevirWX;<4 zhDIg)ElMr_(#zVzDIe?J?M2LdojiGKyf~m2L!FBp0?W4WV@NRdNHaKodSE-n0Tn%_ z>{RLHTe&WTvwFFm*2WK3r+A++2kv{L{x){9XU>J+k4+H+o*diXrCKxDVDaLA?Ij<5 zk7l7$l^{of&jzex2Y5FHhO(z{M;uI;eh)+*%f_`v|+>W+%YC3AjLNo*i(_DV;O;KN(doC6Zc6MK4JkE z-=v{Ytq9-o_8c{(eB@nMFA`NHGq^ar6EaF|=pI7&A;94}UJ4C`%p zbTFUxD&Ia_;*_tc&4`#~|6mJ77e)cGjM_wj=Z?Qn>h;;+UDcw2W;nqtB$U#-8DYcN zZ^Ej(J%`ZL(V8|b5n<2oJ{Ny`R_uGUv!_fsWthK@-QLMbdqq_H=?_Ejy| zrhghUfO>$3{IP>RszohfP{z`M!fm!^Co18HA{1ibh)c%vh=xtEykF4#+xBmXpMecz4@|jSl&Nl!4R_mWHAi2O#+{jxNnO9_2`aDTufsYfo+0$!dBCA_W?^tm= zZ6pBYML71^uCaBjc&xpwJ>N8}ed#N*A<@{|muh5Lki1MMIZP%D* zGBAcizTsfGq4*7}O^-;#EL0t;<0+xC!lTlkX?%ICLtx(b!q~a9G(>AdsE`Gd?Dmd^ z&!EP?N0))<5UQY}1+L*jxE*G-^}Lu6@gPeaI{Ijfzugjp0bXT;zgmtgrY*tqXPn}u z^fo`EJR>VLQJc4h3pcqA6FNp068fZmG!R8Y;WFH%H=O~u@^QG1MFPFuM7K5y;{yYV zu}d_igVrA=F{0!t#Gr zl`!bhERVDmYpQFGmPJcVeJ$)BlFzRKn6*k(**-3}7$ZByQ*Wd<+!>(FJ7Z1Fv zzm6CV-RV_b|0LXJ6;uir34Npz10pII!OMA9T8UKu+nwH&*z zf_X}(h}pH%)EsGxDV!)Xd_z=g)hZxTwinfa2@nq8LymHY6|mzoqFba!Hs#skbDzHz zN4E*6u2b!tVLS7Vt;2DLjTS3fO~O5(wrV1`mwP3yU!dDKv*5Hre-gD~SxiQGY!67L zy#nX9^VTRwz3qNV4irkDs%##C7_0uOu7sY!*;kzSCbn z4D)wl6oH@3&oJtj+JQKv@a?`#L-?gaFdZK2Mqpk!yX@uhX`ARra%L+Hm4-_K!{k5@ zf*x*Km&RGEt1^KvZE7F;t6~N0qe#^LG1rU1clX%a6X)L&4D2oR4DDsc$IhF-Dv-L{ zZW#q#a;*D3<{-?01iVHtUP_>AtQG7~Ly!rzyeGnls)7l{ol|6C^RkixVW-27M?H`y zF}Qw8=e})#)D>~|++}o=?5F`ouUpZCd9Vp%68^L?U^RgFfiumI7rQ=oXk&8wK@fc?GcOS_Qi8GO92F4H)^a_f-?0DT zGgLFJ`GF_Ms8?NF0{K+=BD*$@yy}tG5 zb{U1W_x#}vsi!|M7CUoLA)swIJ#y&6LT|)YvEyiS@Ku~mwl{pH%qs2+XQVw#Yv6=h zFqJ#<1!#Lr((F@0c$$YHpVc1g6#KG(@kxt`XB%rSy} zFSGp6A=EfG;O%tpS-sL{3FU|}He|?NYR~bqDH)Nbx}Y=P%Dez_YZQ+&vBD^7>AS?jCVD-+C4PP$S}URY+z%3@d(hl^3{Jr^)l>U_>+4qfGB! z&F{j%3rIz-P+}m)=_Y$e@BIj_%uz>b0%QZiP`O+7G)H*}N>w5>M1rCVk zJ3=t>!neXbrLlc>3484XekQ|kh|5m#kklV@-Z$zS?Ddt^wWe*U&Zf40Wn- zI#2HIXZ4Wz{C@WZyV8j0xcBRAC-!p4WewixD8#b(7=+A~dNaytTEA}1HM?v@cmHRv zh97~?17b^|ph=6?aq4JlFDp!s6uK_GN!_=b<0Ol(yko#-MpuBU&s>L)gR?5F(w+lm z>m}C3dE!0{yDo~}?Pxdos!#J=&fdPq_HY-n*3Yt6!_@k3pxGYwjV5~(t4?d3tNybu zQKz$#HbFn4`8%4qsB^@&q*p8M7Vim0k?`_<)3l1VO?aCq?a1`b=VE7=N@0m6`6dyE zFg05qRK@^#4Q(7Bn7G^$YUgY}-k!y(O_eNnfgi0BDPy4UvtBE7ZBZp9G3 zzeNv!tE0C`F0_H3FsADR?eZgT*?}zwiL?ZTXp;ierr}xd4Jq3smFnY7s0Wpo#hBYt zP5Rtyr19PsGXDSdda39XPI}%YSCUQn6o-f>pjhNT@H7>b_rnJ;n2JP82E)xUESxmm z?k6q*fK9}$6vxF}?#mWOPN)Oo#RH{Wz^Y)XaMB%;f`fw4GC~H|s31vFkVFY^b<=WPmi+aNlRO zMDhn|LA*PvfXsLq|1+%rOosow;K2+mPcdKsZ9w$$HLK19i5Wrp(DUl>iix<)DeL%4 zE%~?=n5FBl@LK!>k_*9ePht0~9cIF!%{y%h85Mn-EPs+g_^U%fzG@^khj~NdPHnDQ z#s&<1#Qwbxb6q978!gAqi_>3WlYL)Rw#Cb&%6iv1`WE5lnJ|kJzHB$oxbJA=FKPk4 z&7^q;!c>u8Il$X$h_7*CzY$gx@2Q$=l>OEy_7nL$QSi+)65gMOte{lx0mS_M+2@?F zl>sG*xa(7EA#NY_^upHFqP{5(GjRf5S}j!MZ;gm{p^=*7wW=KB-r9>0$%$pFU?^~a zWD>JhSd-*EqTe?(>rU;DW*)o~+nN&q5nSlU&ldhF8tIJD(F|i|Nb2Uj-I+Vq@eaE! z%@Ap58wjOm&Hh}dNASNm1zELuHQx^vey=w9e(!Uvmp*ig+{l&bK{9@VeaXqAyP#;- z!bamBd|V49s29;Nv**y_-hF~*2(ho^2bo6N;9p2v-G^B%T(G9^FDyKo)2==Y+&0q! z^Tk-YL+G=EDnnaU+}+qy@R68~fvs;fU zD~v?(S)1)w2Q}se$uOT_xe*9p6ihg}uj~7AZDEZe6>jDj8YzhM?7{BJVds}uVo()Lh?1s2`z6F--CuncA@bi>pS%NhmM^A@=b-_l%qS1 z-GKJrw(4~UcgD?OAb6a_rHJ+>go0-!3TksDy_TGXRg{s&MIV6SE02K8H{GXaxFerZ z@If6>Nmi+8FNB|6!GIY_N~O2tR{?>M*|2v6&~B3q>)yWOj;W?FsPxCuFh*DV_Jftd zUnr}9{VE=p%Sm6N#hM0y$Th3uwwn6Wlx@e8=bGEvt=pQL%cCPkdw_D8uClq>44%sM z8#2oQ^IW-C6-_(tTv^bNDyQf34$ExFixIt#Xm&i;6GXawnlU#Jt^Mg{KP8xeFLDw; z=Jb-`EM(jES5M5Ip`%uP#jhKdg@_@?Wpjj+)xKtf4js>k$QWcmc=UqwK+HLWz>io| z`;O_U_A28{;DAq*8!RKB9L+NbW#Gm1%JMF99NRMr<-O&z_$KGW)&RpWfP7Pc>55qE$jwA1kNU$mY{avLO8VQV2))&e?2R+TS#H?7SXvjjtN{Y#M#22lj zSQ4nb16ZK~E0WWdVg~O9z~{W7ZVJ_A_GOs`C~H?bK_KK|$XhR@Hyp2I-(t@u&1m2P z=yt>2i9774Yc8K_>E@bs*}t(@g^t%~C9vu+1^dG_amX?w#$sEoC=9-knAmQQWZQbc8oUKcnBd=Vyi6&&_*Yat9T)0CMW0;R>GDN&O$Tkkm8(tLfN!h^)Kr@>5SKvsuWpH z%SW=CGT53hpSa(bywb8KZ^l*j)WfJG7*emxZNjY>=!13uveWOy<4vx#e;vkHi`RcR zt+_F->!@BlRX=Viy^&EFGN@xxw{a-xa<`ZnOR>yV8>XkcxH$FhVW%q2Ivz;UIER~b{b_e7@v$#=_ z>@LT%H*uEhbF>hqQ|H~!K=^I$XYWtbwVZK$KWu+0e4!@(q$$~gF5ewe&Ri63*4C_A zrf9AVD3_^tP%8#6DlNKNC2eBo7By=%nq}x@Sj;hXm0m#h6b_#C|MZ9~P&LXjb0%;DA5%fhQiZv46x~Vu5on9W-S%GLR?jJ;{aaO7~bS{7Wrg zxIuW|F?4A@g9<~E%bLEydDXTzQMyYkA%SobaAzV4V!L5UC8%`DO6}i0{H$YjszXtB z(r_>l_UKWvbraO5QWD!Y8Xi!c#K_eZk$1$%MVA^&HAh#8QDjG^)uO{y;qbw)QS)Pf zje?kWEN(yw!yRU%OOs{E(T>{mWlUtqAc&XtYAi3myXYG`3)J@V&lFY2lWv1gN*|xE zip2fDd46JZ*(pB5P^5TZ<~D43*5y*dNp|Bp9Sy#co2QFvnpVpP8OtpEBsKqpnO>O| z=!+3J=Olf5J#+vcNa;w$N*Y3lWrtLL3dCq(9|$naH7A;D4zrjb4K{5T^;aoLOdgD> zJPFkoV8O7@>9POXeK>quVmN~lqTwsiBdiDiO=5%w_LpY7Hw;5?xu5t36-H4T>|>kK z`Yct>4ui*f-fuK3SV{?!>!fg5-cy#<^H}V;;hiVLgB?mfCWIh-|Bl>yT%XgZLdjTb zL&8(zk88u5;WVp@+!;SVu1U|ls|l+Cf?Og$eNNbcF_ZCRxizz27XsgwlS z4+&GbMbHg{)C?$YGQc3goMJqW|DshvGP5!!&^FQG{b9tgCU|EMP&6R)f*`^F00G!o z{{WRp6GH7kpZ>Ht*b^A+K+J!2vHeFE<6m8WW_jx|r6K!kr$0^h1dttw<*$7>{(Yaf zHU0lgNBU>bAI`x)2oyqp7VKwd_-ny_u|Mw7IjZ*Qicma0C zf0^VjjKzPCScpXfe~_U#(M@4$bAZ|C=>A-PcqieQlwmj^qzm~a|mk+b== z2fqyg3j*s_z$W`EVerg<1^egoCu}^xVI*WafEdL7$npot@ec|Ahfn`ckO%u;Y>{O>fCzm!A#6W~7( zA^)_Y@Sn~9>X1J+{9lCkw}t*&5!wDJBJrOi{HuNb7V&Ryyos1l>4QT0mxfw@M*f4j z@*fUl0sUWd{r>^HVFCSHqW?D%zOnyS;s3TD(!Wt~{-NOCbN>5@EX4RmYx!4`{BTSY(7#>2{?mnT-TxHu?K;c?VosnnMJASFWM*JvVPIzd3}U7Pfheiy<-VIb>e?H= zd65P5mu3EyfAaUH|GK~kNXQu4>k8}I>;5&EHG#g94ikpquLj$n2KE~ah$W%S6qz=` zv6GJX4+2YmhL9TI{TEhBn4+fn66n1L{S}`HivKog`3I@`?S>DUE&NjfA85lE!jgk@ zs5M0DmmE4gRjbnstm8KHMxS{(n;+^IrSsh$vng%;CU$<#%q*MEs3l~9<@hsLuCSwo z&*}@S`*}>;lV0#%sJAp%D(`wQldZZPUW&;Ab&mSXcy0z7%%YI2%BRT+ctv{d7SO-g zioxl#=6+}@N;7QYQkv8uG8DV2I%qy!qe;-{p^RE+9Ebh})c}ls8(T5t-WaEk@}&;X z0KXqq^aiZAqC^B7cXw(&L#X13qV-WZt;0-d>dHZLx`w`HTGo9*@wftEXU@2+W!T#; zOgWAfQB0a=PxT-?M>=I+aj|iG0TW(xgc`tP2ph>Bl=O~!RA{CEZ&1MSmH3QV`v;h% z{Z!}tIP+O+drI2a}>OXXG%sBw+%E zkgoJ+l&nfw*p&4k9d@`b21@R%Wjo*(7+NZWM6h_1wH;9$zbv{0vH?aP#}^UpYvFQF z`YW*jB8xmX=z{VEd$!?BS7W!iW|l=BWf4dXhZec`wa-rDX^gB~J9#2LQjSM-$66`i z2s75c|9s(rfnfhp3>sdLVV=-&5eXrfs^ydJi;oZluQbr)N+PW*8FTg_XCNYnOHv4!A+ z=H$~T=3{J_LWr<&cYE}H{s&7u9X?k|;O8~~+`orH0SH7eFH#7`!M}g@uz=VS5_{-4fe&er?JVznkv>F$_1?djtDo>3 zreGnY1_ynj2?_JgPBSa2Dv%}v11p6C1B3mDl#CRLl(C{ujKuE+-hkAhN4(N^jRFF! zkNe71Ue+R)JbN0<>4Hob9F9-RRvz8V8_G`?pADGQ-s*}xpRr#m<6jJz5)W_gYD_(W z$C`sX0OszTcI?D>>arw%PyNZW;pz8H!YQk#2kUY1!WwPI*ZBm#lo!X5>o%>+N8sqe zfC)!)>i8%?GsB#2o!lN$B13G?5utw%dhMdgaP+uKBq2Ot3&CQHv32D8k=5J1A9WBe zGRTSUHreO>Qg0w=MQa+_79bcq$v2b7E7yDk3NmPP;tjuB)@;nRdbHI4ETiesc`W#D zRI^08J9{+Zub*ty(87vhvQ@TX;M}rt++rzhec9IbI;3GqBsZo3xoXhp-(_$Yu-5VG z@?!%-+srQbTD{a#Lw=@=6eg8X)n;R=WN9zu&2J2TG3HgQ! zV0o3Cz9*G#z31Z`--=_)>|TKrZ^!m(Ve{&bq6yh;P%Jhnr!m3hqT8AAKctI^3U z%iPH?T}A@_bb2QDhHQ;=&AJIN_ImTG&&KWv8%r-#2mNP<@l1rCJNKKIOb6E-)vj1J zb9)x$bFrmXTuhB0?<0qP*DC^aqZi9)z^g^M{t3-k8o1>MvWdAPzeWvTfJBb9IjKv4 z<>TCyMLW0A+yPH(G}N#uVnemLN@(=U%B=Q_MWDnQoy(oo!GgPP8CBu!Fr3e;G9dQ^ z?j^9?0TS&bFyE11Zq6a@slr$p%wgv}Ub_chl;7pHZrKUr|2=D%csY3NI7I9TEG4fn z?(K3l$}k##aIa+p%XsHw>0}w-R6}F;JYV0xcK>o=3K_M0PprEFy&2>Y3Rt*j#0ER>U4{ApE;r9_+Th>R9OE>rWs%~>k0FoE{DqSjd zeemZ7+rvc&b~Dc*8<{!2&emtJ>jpq(40JSy55|{oT+=dPbJWhd%2a^kZ4cX9zQF>q z!SkN{;^+kp>@|+*6`DVM3vlrm%?XUAy)qDfdJ-2LAX@0Fa^v+Ry5Ro_%M;ryE?9ql zX%M-5%!6ms!{FYp1CkB^^jT>d@?F!nu3@}RSzpLz5$2Be?;0Mr_^O%Gt;snYT>`A< z(*?4V-UHFtVZ`y96!9EgjG1<0`L~hdg#KPL8@w@2n7fELD8h*5s+QAQx7T zmsWvUsMe#?**cf$)49Fj-N$rI9>kyTf;%*fx0;$Wprsd_br~596}sI-1Eq6qZw&@joxlgEqy0o?86;LsLZQ1oXe6%8b zP1|vX_R>pva=NkM{PYXDx*0sHZRv-*VH}0)#2V|cfB*pLgMfz$?FS}DH{Nkd+>oiN z^5|8=*UkIAT1d3YE+#BY%bi<1IuuRbJ&bTuq&haLzrW#JAS4&oC1^!R9PQ#9TtL{S zzwYK*G0v+BDh(o66r2n^t=1zfffGXPM9!FJ4|Cn&*F400IG7TAz_N{IRIv`&n6GJN zBn%lBixbc(jkST2(j}Vc!+b-$HZT#pe2doI&u|sVfQ~C9zP;gc8yRU$i0&dxM(P)< zx8L)2c+jQ?icqwBC$~|)KdYpdS6B{xx{ueQ3YKrs^H$0{2UP^h>-uV7bU#i^G|Vqz zQn-x|K$JdqznGtp;0ZC=0x9=V5Lgtk8MWqd0)S-K?E~(B@2O>n=m6cRWpsBvXaorc z3x#Ur>YYMWn8drE-~#?t)lr~L3*2DTE9QvcEF?@2T$DH(44i4sBwHpQx3DKW_cQ-5 z-!Ee>F?E!+SCaOVpWk*C#1`dqkQc=&NzaCtK?DRv61})O{YKJ!uuIoS8a~t_Ch-jv1(&4y)Yo&FtEkZ?Y!@6sqAl_7bOCxeA!NO`k=7oU>DfW-e!jut=16r?U)ws zQx@+0I9`i)UgO#IqcDDBeSq}XI)KJb!d%a1&a+-$=x6jrTv%~wVqj@oofi|*#~>DJ z_yU>$^@tdyQOwCB2D$%pNvZ9PwOi+YKb`v=t%*_3`B5?w&NCRO-*bn!C8ve=^dW48 zR{SNb{%66`youY+qV(7<&{H>|@~Rr3UDX2h^HMrwFRAwD(bsS*I)a=fJOH}i)~!kt zM7g_K<|WUwc2;8b{rR+|ZAEtJT5LtzN`IWTht}i~TxV3J;XA(XKF15VfrH9eMFw^K z&znP5Eo|mx&k#%SSlu^(Z;GDA@(I0-NBu1f*xR%Eo>TcasJjWNS>|>lgP>9@Up2Hv zyCEB-7-N(Y-^|}rkm4OGu|U153LHdkxNl}iorDhK(`b2V^;^CB!iRVx0_90B&^nPE zB#a-P8l*YXoi;nz(aVt8a&YM{^uTaHH{5pizM zC7qI;BsG)r(WqmS^=1dR^i{KgWii1RgdS{OzB0P%8gFdFZ?c8s+3^{;h3XMsGh;ei zV`+Hqh*;6#>A5a2zoA)&K2Am)JNhc^3ke||U@n(#-jL>fS^*#p@`<7ZdEe6Xmm&1* z;#@_wd*H@zEC6lS0GO+z0O(>LQgEetn?A)H`_B2w((ChUb9qzd-Tso3#v(Kuem(HK z!3GthzoxVFa?aDSo?&UjA2oA))M4r2`x?ICcGH!((tZJRO5D#fN9fyi?Pb&9$sOXM z$hZFdV2e1XlgT|-#s#6>RA+8?RL+M4ake#Ax;tBm&{y67ynxgmeIR|1mY50p*RBU` zc>3wjmdZi{JyH&n;YHooJiY1zyivYCGDrs;17j?B;sKC8X8f7vx5Qn$&gBA(h>th4 zuL~CKt<{TfUx$U4wyRB*?g_8|4@+Me6xZ`~jk_%nJh;0%WN~*VKyVff?&RX`?(XhR za3{D+a7_pj;D_hg|6A{esoJ`=b??-4&-9sdrh5W9Zl4}mc1oYz_lXlK z4x<)U`IFyRQ5eH}&wtI>Dt`e;2$6x^f7^#|PI?WA#9C5L{`6*+x)}^?01X!opUr^ zC-U6becUMBukf2RUFkl-o_bcs#eI#z{`L0v1}&U8*`6GwKiQ~i@{v67%{bN}A&IO5 zgnOQkKgu;EMEEq`vG8e3JiPal;At6?BD<#V*Z?Q|jS+!m~C3te`@nuUg%qukK^8&j3^ zrj_)Z`}7iHstkQ0Hu;9E>-OWA04fX*TFSm&{SOHAsTr;RoeFRZAL!VFN!jsnepPO= z(`8PK(RcnomD?-+G#hW&j)MQ*ks)fM^iMaKDcw$Bea3c~x65Snl;yurYfJunWq4Mh zo@+D)@K}CwdcD!Y zB#X#eVK-s?xI57t`x~JR|2d{WJq8__BZ{y>iz?6jJQY<&saG&0-P^_4m7AV0d?sI| zC5o-cy6}g^QW~pSXAuZZVG@^K5?4tIQ=oN_#b5})>{m!v=UIy6y;Waw|Djy6?v8no zLWY%7kIL6_)l!zh^fmShDKzAmo=>qMg_9El1Kwgor_I-)=+d1=MnJQyTM>Dgd@)Yj zz`0b?ql{nEl}6`TNaZv&1ZE}UE?6(# ze736a;T(M2B^exlHrkd|&pP+Y4&(9{OUC62(XG)<7W|8kO!yagl@XGfE!~m_!%kqq z1tk3x8}6*3k(ec14&l-CJ1ekNYSiT9SqARKfz`vQu{D4-^?PF^Jvn88Bj(2P4gpwC zQm4g79ZfzyaO1>}Aqf96L>!4}L)lJN)SYOF=LCV;W`06S|9`fjQp7T=%(BH#ma5F+ zvdebrV)3eOv_vC7(J`CE=f%xZ9>i=x_0MCLCP2H7bpo4aeH)BuvW#ln&O2roLt5o( zlsyy4C@WVS5>ZYIy^??U%Yr%w=viPBM5z}Y+s1t$Qwy^1;D; zS`$@AGK-<)i)dC~;zsP3YoC#64nk=A0BzAo2ggx3DT1wLg78hpD14G}>VMaUuF-4W zUW*lbMF;IZ?arGB;*Qr_qDryTZp=sipr+l3#7#`5!%*Nik~go)O2{s+KzkeI<58o* zHiJ4<46uf(z?wsDXPvFm0TC^X6%EY_4x_>wbAY=t$k|g><9_+8JV;%{%$k)`NQ#3| zJ(Rq!9d=yo>TquLoA}L$KM31cd-r&hi}PznhcPu8(`>l~7BBtgP*cqWT43lVfmaZs;Z1@bi-NO4Z$ZN4DVyQh)+)i9%em9xwb z5NmV?oHp6pEw3cEdSI#U47RYEG(He~)w$O!5%8^Az~s{|x~!};{w%A8y!;)-_`}ze z%#r`CNomD~7;>zJjD`oJHh7fUYiEaEe>=h9PC<&MlmAw(J_R zisB#s8Tb1_6|H~q*i>S33e^910_QzS!b^(zM=F~*d!<@A$+XQUHPf4+A1Ql?^*m1q zsuU~9uV7&)DJdo>aV}N-`iEDzjkOO@ABP|2zq!>OO|}|@l}bm;ZidKXa6;m7IQlus z2pj6_$_TTW3{M9p&nhda#>TJ}jTbPmeRMywSvL$=NxaJ=r}%5N|WR}wHE2=1j> z#%sc+xlxI7;?PI;6re;YmDW+tzzCN^Ibkv>^7OAWtRqmB{nE+I2{}_Y$-S1sXY??Z z(gEiu(tJ!zeGG;s|LtXdgKI1?J2yF_d;tbX4wM*=Xp&C(OB1t=>ygV-&7ln@Ad=Pp}VsU>GBar5F92Cm@} zR7U+K@|x}-Q^D+@j~Y^~qd0xh^i1PgqFa1QU8fEiwZF+av-wO!5yrD^LoKO`0-njz z^Vy?mHGpe*QA3%c#+$Ie{X&!k9S5867kZ>n^y$&I#Z-1|l(Kou!Tm z{CVbyk@x3svU8A5F4qXEeR#s6W<3#h`gPnWPaUri#wBD#&Sw%mWsgu9d#ZRY#O?Gr zm6)Fs)D1hR^{e}YH!_2Vk*V60lJ_PF#r41M-m2dNjNJt3l;jr^(J~_~me?4O^>6H0 z4vv{34;VV@b!z(CN~;0U(xhz!aceokUjrh_BQ4vx50%^eAPz#0JvHQH(KzUL~Nx?SHY9pjklvhXy#E?4s_>#a_o$5kxSX~sM#XRDb zR$~vWgs2{i6EV&&!<0z6X4OHN0qCPa=dR#_n_6Z}SS(U{Ao_18r;utdDGn>Ss+nS9 zE_W06O{`+=FQT(2+Q$?6$mrwPKbzKEQ;D6GxW5dyBU#6<8wa6NmeR~ddv3P_B<~s71;w)P=_T|G^`OTJaMyBQH z)mLv)mk@UqLzwHHp{vxpD35S3&yno0v+d;a(+1eD`k1L1q+=_O;$lG z$3pR{`jmywrJ4g?@NknB`l{x(!ofpLVM(WLw>p60Z=}$v;&klrh%N~|_WD)H(?iu> zCoq^zIt2qYjp(k4dp$RkotU7qf)q!UytCSvOn;Ap2w!%7Z$#Z(fD*%<-~5ZX5*Mz- zJFE(d9jqU2i^X{#MvB&itiyGUjNm?D&<4E6Z>nnV_azXAf(Z>jv)%cEzHjR!Rm$^x z_$_b{_ivP51<}G!qR=^<+vQInor<#gcYX2fI45`^sI^v_Q2kE_Z)zOCmmjybs6$er zi=?dBVojkE!gxBloa@lnv2gTy=n|T0Gg#NWcqj{NstetbGzD73pn19*> zjJI+{hEP8(L71~B7yiA<1}2=KEkaVXfDGDl15+~}!`_R)k4o!jq@DY7PGA^36kaly zEEV4achR=+)lYn!Aj7L#l(-aYSbcI3RLjqHmN59lhtg} z@_;Vd)rPwES0;RSc(@H%kUS$NDX$ELSk;I0Wom^w(5aCqW#SSHUM&6TywAWK(t>ko z@tzx<)Jjc*)UZ8H(0cB~a@V~fGhZAJLI%jZ9o#S9p=_S6O-Wa#8{}^7yF%X@++5F5 z5Vmji%L2s3;m9jNO}%;=y4eH#rt!JS;W2o}KgFti+E$AJid} z)|@V1GdGFZ*r1emkSB+Q{^wH+xgs{r z$JsQ8xa`XkyK+CD;h$GPpa>OjEDBbEW-d7#T{EV113L(TXLFB1X?(E-Vn`I9_=DvN z^?=WPyL!F0P9OV>&d7v_K@tZF)``*|X48yMp&3d`{{n?Y$lHVea*uwo{R|@Jt zoeZ7h5IW4}gQ_kN3qs6k2dtE>=i$wc{C?wqF#YdF(8_Uhe@?T}4?6$5+;$?)$H?sJ zdl>tZ)#G}3|CRXNx}LSe^KF%B={e7rt`oS7{7)n>?<>5}t~uv9!5eM8SUuirjp{Akt@|(pgwno5 zwDCOFoF}^d=}!WV?&aY3x_1(gU>+7=TCdqUpwgDg5}(TWzdRcb72w8k$=!d;gJrmW zCvZTL&CuiruPJ9qbz~xgDv|R3^r(YtcmV;bB>}D3bPnOe-xh6OFs^@h-=FmLTKBb6 zBS{#cLG|L~fNw+iO_P5Q3fK`e7;Pe}$ib4x$M8sKWB1si@F&Q5gG?e6tvYA$H0zEvj)5HBK`cvM|-Q2WH) z@LAaPa(F@Qt2=1)E|3CNJezBHNu(T!B@2<2nTMw+2zze8l4aQFF)gP_(&3yB%WOJC zc;=km*}(^Jw=(mIg(nDVtB$&lXN&&vf%bYo8WwuTELO=6hkc#d0z$lr-;t)ZBKS6g z!2GF+sM4}Tvy12CneGqY>OcRg^AYAI6F3q(*^ z;rbX_!*>FmIrW8Y)_)e{G|=4BPo(YIZ=!EWux6qFmaMuZLM3T=Zv4OQzMVq{1vEWE z&!n}Y_VwK--T%jskL!&>h))Ke7D*h;Rh#8|iu+Mn17{SPk7FU=3yzMjJ3mbM4 zXH5izf<36*Xi+7M(%X#!+NIDxDdAD#Y1w%XEbL=skxy9i_Mz46=OZ6ts73v9(_ZE_ zw{~dH8aw-KN=>6q3qvCrI&N#NQv0NZ$GuKYy;oxE!gaDNAtZ$@fq?meO6wGn`(xoO zgqZ{>yrb{pA|Eyr1pzNw{|bVznwV31{S*LD`xhfYnTumebhZ7?Z(->Uf^ys@z3QfY zov%YA0Ur$Bpz&!VSHu*a*7+star^yzM%qU5&a~diM3IPXR%a=rp34_@qTuanc+qru}+i02?BvstPr+b6pp>j3Wp4zF8WW@3wlslrU>!L4sLmp2$c$L>jTl;#kJ zPuW)Pf`PB;S_p1G^2ZCi2t(ZnwA&EWtd?LpekQ`vm>3g;H~c|9>LXzt0ZL2UCRw#D z9Sd-sfB(~nB@|XtV#KBYlh@3u+Al{&NGjj5Hz_%u3!S)h?{W3GYTQ=`1f_{qyN}J$ z8++Bz9o0Uome^yJZ>@CP9pDh$+^P(@i$%UX-^VwH?W3y{T|(mlX8(tl>kpBzNa#dq3%ATq&7x6? zbMrH?och_6nEkPag;SsF^Ijy|RuzI^t^kZ|O6 zvANlN(mT;Qqw`>4K^lqJEfjXcxNcmxAp{SqRfeI^lrr8EjOtf)iX&?<7FQK+{j|rV zQ2ER4H831W&9#KIIt>+#ydKhV`jU$n2bJ6;fB5#shs}vOn%hw5MN-6j0YrB8^c{JC{#?a&K6k$Ih$(|5hoM=-=PYZ?l0k)Y`% zVxCkd#z5Dz*l_9h6CzPcREgsKQCNdVCorc*GG@nyF0ULt=t$WX_R3qUU_X|pH1!PP znpJQ^4Z^gvb_im>Q&+~G*vIMEZC$$jugX|z{-`7?zIn*bn~FD9^F!ku^Vw|@XWwI& zYbiOdfxaku^~l3r0BdheAe~Z7MHq@$>BMC{F2GVi5)$}HE4&)rKC27cmvc~;eNWM@Z}s+XZ2aAAk7gW zBu~-&^o&qOwt{N1ssd#K0?p^-EVAl)#0*(EUII!y6EkY{pv4j4OMA_)(^a#m`6dfp z(Js)kb;q|8C(%}iBtjErUDNc}@o8bsKrfr8Aw|qt)^EMN#y(OUf_xqJ5eO>{Hq~H9 zI^`*kOiJ(v{Spy=i*q4S)smW@X`3ICn@MqK(MG5H@zL(lnh<hqwN`BtO~g+Q!XY8IxXyMZz&xK~DPHEL`h_6tKl939pq*n+gvgCshP6&&EcEIRW#knX4qxXoZa)zTZ0c z&+C(u6*b+F<$3xPIUQd#cWL^LE&k0#E}z3GTs+JN-NlxT)A9bg?%a*O7j+C8eh6bo z7ZQA|fqVIBV%OP?UP6ik7;=Ag7+b6nnjHzvsv+F1B&cnZDIyyh>p&$tL2=ElOuo*y zM0j$*stlltr&J^QE;)(&4N5YLKv%m@rJs<5A#4+*9O1_wx$!3yvS)OT|H1koe}0rq zs$I^XG{v{CvoFmbnjdl=jbam%6)N;xQ7X!}n8z_PSqL&>OG~-~MC*`G?h+L_w3Z~) zs-te0(YmDeOq*!kLjXJ*oT*K&80GP!NjI@ZG%31baVmSRo4Id;*ZyhM4GjX2^<))HMfqIC~9r`=RqtOkz zctOxQaU`2uWzXW!bxdj4K4JFy|08<+Lp8zO$#l}K{JeSQ!~dV?4W%V;k@_l$i@uh| zx{sNx&kGI5;e1d+*P4W6gD%2(2`T~UCXz|U&23i=CEs{ucP)i_k)rYDP#yw2h*(g$ zfE7PFs7bwY+*BA1A><=s^LE>9d78j9$?wS8J4u~1(yB!p@KLXK^>Z&&%m_oMyaO|o ztl<=Dhry)%#DLAV6(+9HbxTv*ClycXIEfO3613=i=phreVMuaJVi@qb67Vhds5YN7 zP*XjKg45jA4I8zXlB{!;WdVn~)PpDnZYdC4d~j4~RkoE}ym0_|r9~S75<#)DyEBt{ zNyVwu&fjj?#rp zvR)b3i3znZKUHl};VWg6QcQ*>C1ICvl!~p4GaS{%K5-SgD!u|X5Q&?&cM^(`!uoAc z>;;XR(|rTsr#}ZrK4p{DrSpM%DuvE2CQ4Fl@xm{u3mdXb6m4hff?WsE$VQhN4D?mu zrBL|FiW?~Vr6J?=@6TER)6CHAdGvi?$8qd^4#D6Zy97&CcAE0AkReSGo5y7#9r)Vv zE@;Wt%@aNtE~WYm82e|+NS?OEKrtH5Az8a&!vDJrHiTFc9TaXvnBdDg5woDEW5UMySq zNTpsAhQda9)VyyU9wwm<6)zg9&BSRi9$Mxfl-RPc#f?G)#I>HAXXM^cMJ z7)3$|!U+I+DBnT##>FY2=yGezBih$;bv!yZ+;JVIEOB^_#mplG8H3MO-aZo@Sx(x|MM zp|9rPB_P0tOD-f}+l@nyLC%I_ons>)_-YB_Py?XwfkPR@(cps@qZdu51bau&K+R+@ zw198w^P;OSx;&jsCx#|e6!t|3lTh2YCh`F19(jC=dMf0!dc;#H*nVNECp0la6MeZP;xi3m9YhL z8W5^yEO|O5JE1P!0{$1c*(V;H>pxEdEs@dM?X-q7n59ThD8TE+*GPMU`I$+yj@t{I z;%AUg4-%E0JO5x;1r2wyBS}TJadQ`>WOBN`M%~XyasyOkWXLPF&QuYz^|?U1c9fu=kB03*D@k&3c&KQE8@~?r)0-)LUgb1D-((J4IX^Im!8vhn{Eg8Uz-OlH$HIXffg4eM*Y`+8y*CM6mbPb55J z2b{ntRA&oD5}=9&Y$!KC_R|dT4S-c(FC+;6t2uxu5tVkMW1fpAi{3n01knfDQw&1K@WqhiveS*id@PS13!eV6$&1E@$hm?vPSJe?!XUVA>dwm-8RT=Fp{wv0i{^Re0&+hcuX= z@I0MC5<_u9y@Go^WM%Jl$SesnCUO&EjqEt5brnZX56!&r@N|e&sMxBVV6>v6D7})t z?}|-kd1S^HN=zbF)It(6nM0bt!ZKX>v447CgYaTLZBv`^^$tf(&TK0DeKI(|ZAR=? zuO|{U?Y@X3CuFrGTgC)Xb^;S2lt1AsuHRt84ToRwt{LouOrOi#eO&%WBqaGQ!+w2k z-j7`#W(a^yO2>fb4t^bkUQqY)H&y=THfiNuJU>=EL>?bk>Yi+DD=aH`I^50Vnpl## zQFgACo#@B`K^&0+Rb4kV2!*DYWV)piH(cGCHDUkz@+WF^ze1qY+!)bzx+Du1sju|z zfOr8V1T+i3#E?Iz(O|wYrOty8Svv?NQ(Y_x#1|lDol^AJMNb;M-E!QbjLaQ5H8a0x zQC)hnOmp{(=fAveb2@0#?Qe8J3xp9Ifl{QxCH-k8NPngjf%BOIUm10{oV6{E9usnW z@5BZo=QWwkIDsQF>Q~md#o@x(bhTxDcq}KreS&S_VvKmBfDo3@iV!?!gSgcP568qJ zFgcgBdFucjc;FrWjC>)=7S&8rIufM``F8nSxjg!U!%0AzHxIJSXMAb| z7=y8}dYK1j?;#Pu#{`X1x5*ckrg0plo{^Lh)vGfKhqI>W<9}3JxB-hdYlTTJKqp$l zuck1537p_3>FTxK-|(niniBgo0}ccbNBizD8pp};MSgV(9mfOA*x&g0pUKM5RlZV! zm_HwN0wgR1o8pwho%q%GhHG~FmhK;Ng|znp@E@j8gyN0RgGa+Q-+QFxpXILq#k1!O z_#qO9tg>4&Cc3RhUq=6f6+*~k^ABzd_9xpgNkcsaCE@f0Psjytr<#X4rLJm81cEd%Lmk@gbZ>aL z8#x;YidG}vyLKcg2!5(Rds8Va9=HcNFJVI6+%zeT{M2_FEbr-Tg~8F8Msu)7!U$M^ zzSlzYJ(MxoZ|&GR6QB?2!xG1R#Mcf{(9AK}i*T+5e@xps*AV&TRzZKO!MQt|K(Pi% z#oeFlO3I1>gKBcIc_ZVU!ji6RESh=vQOgrZm>*QT&2R!g(j!gZLqCjDIU=5rK9%IO znqB3fd?ElnIwU}OedQ+RL<6vh#Sa(RV#b@xa}qU-Ued)W@bti%A?c9RXa7E>P#lBz zbasK1L*-DYAOcLhGnZGl=a3C7iT!V_x8=SHNl(D{! zmH})s`=vqd)%Dx7hqIojC9)vRzf9i$rVa-#q!iM^N1(x9}18^FZE&&fs1x|RZ8=c23!hj%A& zynGT54QpM8*9Q>rW!sD^v>b>cN6`qF#>95w)++wnxF69fpk75*nm=*%8bs%xLtbJameg z;B1GfW!;+W7-(!YLA(`C96wPCYp8JO#j&C8v?3oJpWUgfibU|NyDW!Y-sey96~}F!2{^jEQ1QFZZh?DjIQ9Bv=pS>nXcIRI&Xnn1`y5&C*FO(@#o2HKqQDj_qesgaU;`zbtHrv_zO<#@}NGIz6Xfm@a@wLMy)pdf& zEMh5nc)58FVU}=VC@CpPa3*Dz&bgKcO1X(d6LW_vPH7F4^ z@S`LUK3MYc!RR6}3?edOJ&~@jfkm?>q;?&@V3(?ZqIFE_ofE00byaw5dz2CI&tL7H z*;c>T2VI%B4eW#g+>Dki4wJ@5B!nM5n>P&W-gGx#bN$t{{YW-H)I~P3zGOZw7Sc_b z?t!;FDWbdz&Q6LF42D|lo3`!f&^qII64dv)8fK(cPTUDCyq-pWUIqKEEP%P{*2wi} zL&g_+vq&vaHPx%xq%d2RGZ(xQ9$*Nc6pJ)=FJb zs)c%ucA`TM)e#+Su)23V?48wS-naky@qQML5t@1&4ZNxP@>@jOYOFZor8G``LL~Q*{zB}5I$?O<4Qv(dqZ;HthRosPJ45XF3wGCgfey1OW&COv z*-H3M1^o>DIqL@+%FC(-|G|pi1fPG+OCIGIQONqd{PMCFOAa2s)b`uQ%V*>nYY9z# zu8P$=Q5dPu(o#mAVVx?JuuoIJq&kSuF`#M;$FO<_78o6L|1Nbpu>S{NVJ-MZ?H;ez zsOi+3P?#s?2m44dmEc_Jc-Jo+bbwj`J#-JP87uz&pOn_>N5+7BtTEdx^7|B>E4k%} zJdv&EeVvHArXN$Whn`8Y6fUUHn%e9^%UO>CNp^)qP~`G!vc1p880+`#f3Rsc-K`k$ zZtYRAz()lR3%HuKwX9>iSj5oX*-&TF^y)(|ac?CTK@)(u3hWllzw-*Mm8!Gq&R0># zrfId5xZX|l!1b+nq|%q4P-+dL9753%V<$IFixiZo+;l2!D)I3{lLqxeZ|gFK4#{)v z7+N2K1m)2_Sr1VQu|M9zB}&kebC04?=iX%b}i^ROV{GTwb8W~2%)A@H${bij0z@mMLQH=|YhQ!5HGjnd_BZG1I7>!*w1 zlyugXapzi{SBU9e=5C0n8kebOSV43-6;@;nmxmK|vdu+G>SyxCR5z`X4ue9)z=#-| zlB8c{lu$9F@MZV+@m3d0(n<8|R{jz|PEpO%VPL9)?Kl%67wu~3HUZj1ef~&=>|s~| z`!KQsB9F2(|4){ihDcX~QAlncQLL4QBcEn>MMh1oF>x9s{}Huqu7Fd9XMF&ddOXlX zNV7`KYa!|82k4=gcp*tjP|m*>u&(}?geTXjEGS0`oXQlg_)6a7IrcB(E(ml_kjF%k|I`n9$B1VJiErjv6Kyu(8ucY_reL9RzaUD( z+*|*5F_p|$jC#gP8^@EBT@EFd|56J|r^TnuJml~{9ZhSWHEIimZ#4!D*!c(}jnIB0 z)Daf9G(@53y}3r3jp@On^A$wTs~*ac5y5H|@_aMpDJT9rq3(x`4!q7CxGJ8*s1u&= zA@RAgh4GJknI%x}Jn1IT{b)01v~)XsxGtykT$gkCRrO0bSz-%u4!YK9X2D*uC~KF! z;;Xw~fF^=;FGE2@LtI?*Q{HNAOFXKvSsx;t2VdoX*y0j#Gb~wDF!#`)pms~353Wg} zq>w=ER=<`@kK`qy2LdU_!yQLWmkr1=6mdjYznu8}r<%2);o9YzZk9~!^jDkgN-vyR zW^uDI9eJ`i_rx|>PW-4M;y@MaqAU(Y4-H>_ER5z-+6vt!igF)s@VWqV2q;EDNBl;D z^RWPoU)plTDm;3#E?K8`s_kD_HfIu3>@3=`)VaoLmOsRR4fN=m9iX`nS7>05moI*L zxP^Pq-l65civret2Y}=cBb^_LTTOjKk2rV*{ko79CNY&#E!o8PXRKNyqls;bXC^DA zw*1Ht-Im?4HR4Bu0};}3`4rE+8(&IIMK(?F8F1L7vq?S&t?r9u8aaE5CPn<^F&!!< zIJ#*D!-57Z00$576|K$841W6^P+6$5%k{>s^vB>|Ek$$ovsYfXx64{U8#w@y)C7#KBR-l*4HS75e>Ug;uHeP|U zy2(sS3eiC%AOD4uH(5E9s;VSw-ZTi!dQnS?t6KG$0g-pZGi@AS?q0hdmyf<}*H)d# zD!8L{$7z!=)VG(&g-gYfhe{+6KF?G{L@+TlQ^*b)P8qq&4+-8}H3`b~i$y+L9HO?& zscYdnNHi6FGaW>6o!A0-?#V20d}0?9v?wtdPF*xyLD6G7HZDOxfOG>JLs*h#u-LT~t-YdGc zU7yk1?cmyp)OV^cAifx}x93WCtfr{~Bw`zWskLa(6pO34{ysvDxOq%{jhD!MYm$XX-I$BVah46`clJdSIF0%_Ro`yu>?&h#cZi6 z+SaGsNsVgYwfZVyL8%KXTiGBfSQLZF1`vw>8MjpVt5wYGj&tKl$CNV?cBG=>mOS)~ zTCdulg#1p-3cHC%1E&5YohK^+!6sp9Nvig(!6Ko;D<$wyC@F!Lh6wEgJ=%$}Rfu1|4gKE4ju<BF)70x^mRQ&+oNMn3Jnq zKVun(Yp<((+Y&S`snEH_*i!L{h}FzGu+TRWGIf5RPNb_B>pWyEUp5(?+4e;<}zlk zENTDj#ADERQaQe-N8S$a1LqJYeQ-3*f3ilCfmnafm^Wm6emzVhIg@G)S=IuyhRG+N zJgae6A}KJ$Fuu86S-h@k z8%YRx?z3?GJnp^)TD&aOHy~+N z#T*!_5aAbF43)-2^^h=x0CQu(^zFc92>pii^VV;mH~?*Bt8x8fSzo#xGSh{80NV3^ zBgwB0lA_OA_vm!v@}t&LXp*^biDCJ&Y?CCB_}Qas21fCR`-dortu2LhL`~~wLVdW?M-*$eQ zd)Y{Vq-rmZ7p|2xnY!N2W;5m)0>g7>;FQU$!#H|9())DujX>-E z5-IGv*sumIA%hf9Ix-x|uT;qQGwR8}H4+ht?RVk!1GT|M;TvnqK8AAsY60hGa^3>6 zZbF1VHs-p2i6K`JE^caba9mn+#NgO5@0NEy3e#7#77EAi9Ka$gYx9$3w6<*cXh09k=WM5(A>wYJoN34!GuMvG{TW-b3y$2XtW zKL*pU7DLx4n6`6p*0e6MY;)ZO$9ohwDDJLT;V&m+h(TlW*PwH5?|QZUtMLl>rAoM@ zV|jvKW`!S&uzdA~Sf!bNlFr?s6ilMr&Yh?F{-FDC?_DuMO}kV?6n?hk#QHb{CAdE+HFGw-|(N#!#+tJ`(FAXs?24_fOBzQFYp^sQSE z{!anL=*NpwXqig8_$V=k$PEK*!^K{CM)GNIu=& z8GKUh{DdHA%AbaGldZv*sEWeRG;v@Bk9w_njecWIp!sq8C3i?5jOCS1`U2Z1e`*7f zT%$%S|mJ7WWL7k|((GwTgTK2Lf5 zjOLug1DG1^RTIc7ZT9f$3=$3Gq=aI?H{yZV2cYFS)L->gg36|`VI{XWcdSyw^E8=( z6~nUO>0^dO@?5-RVqA3G;I7@$jQ_s+#d`4{Q79_RxV+7aUcok1Ms3tKKYgX}pfqOQ z`DTyFfpJq@eM7KLyx)(t0cvmBXpG6>5mkxo1^$Npy()WH&dtx9jPmQjHhpEgS@zen z%)@#+)2R}~K@KzI>4L2mv$oI#a5VxfqhwJUQ4m2M^>jKuWTDs7SrXrV#6uoX8nNO~ zZ$x~`^0&b&p-Zd^-1_nOmzv}fz=BN$h-tYfX;^0Ci-->#rT5$`r+8Q$cgny_N6`8f zpzR1E>*wMEDBQbQZU%3tCSnt@opaP-&N5vh$hNREK^KCK<-;@(pXRSYb#G4Vj0J4gLxb55PgOutSKSchp= zRo~RMH_7sOLMcGQKet3Mfu6TO`H!xRka6RHa9q8AOG%OB5A_5H_U}AH!AzI6NDiva zH{=Ko15IAkqThHNOv1ms&)oM~}64N{ZK+y_c3Xm#)%c6x>E(rKjrYBP+OU zzbY};-?MB+zXV}CQg(fGah%lL0Cvpd!bv9UeK8VUx6QrRu%ZdorS)AW1Hi|tYGS;V zD5@9~;Nt#>pb+SWbmyae0;S_jc=J!Gk&m)@%5SIQA@Q}41^VKyl>(_Hc zqB3NXvq3fJm}Af0%m6a!9?!(;6)&DB9h-!i^)GOMI`B>>g3QyH$MaAJ0oSPMYJZPR zWd~M-h0e$&&{^N5k+}&w5y*E5+l*QkN;LlPD1f|nFicN`bx39QLl-{97P&WAB!rHD zjTK>191r$Xp6r8Nc2_-qW4AkPN=D_N_UP)ohRazNMzZsHaC1!HhOgW0L{z%iOX_y& zMf=3RK51pUrK2NJ4$+-vzuW2GwYj50T{bvNUA3hOS)mQ48KS<*Xn@z}-&*@3hDmpY z3v&2jU;j$F4~fV%@ZeYdr`P4d%fueXF}T}CMIROm+OF~X&wQwq!k$`Rjzh`IiyWs` zF{QY|!@dEOVm^tG!5+4k0s16P-v$IJU#yVf8OumrR6+Xtq@>ZKuH;@&F)WHmUb~F; zW)o^7R8kuxFg8_0In%^w75X9wZcn`F&TmdF)(uK}1>1 zt=_br$oi`}u|BVadz#xW?zQ&5U9Ha|hESXI=|9?)A>)e9L;*mv4*RF?g~7k?H{?lF zs6@nQU~Lml(HvnmGl8k*jVM=XHxvT2>}v4g&Eh^>%_Bl6eVMr({B;u*84ZGIdaLYV zv8|S&>Mpa6YFIEn4n_>(VRi#Og>@P^3{I@P!O>dYJ-ROVE%q;1-(L3r0E9q$zgoTc zFf-H38yM1f#T8zMG&FY!Kt9 zW6*doaKs|~dgac4f@u%Osl(KtYNrefSi;~qX_7BouC7LyL1rM#Uu|7mjj#PiqdS?3fOf)Zn6Zy4N**fR(+;hYZnhZe>`2t?9#XkL&fkw z+8DWz&5Xzb!lkg-cLsa?nUO7kg;8|lFg)a315!*}O8!q8sDG5B;bc`7&o_drD%fu; z-ho0Q|Bb=IQ;NcG7EptVKDFKFf?^ztgbF*AUWE!Rwr7jIUnbmNG7%gF)^yo_c45}R zVytnfsMMTn$KZ}+e;Ospob@YG6zlYgZ$RjF^g=fS88ri3IZ)pkDXOFPPb%I0N^oeDfMjGIc(>aCw+c8^-*E`(}2$}~QQrX3WNDqnM{e|&`yd+s=E98?CLPzOcC zInBJU)ra$Ct5pg~NFEcC-LMMd8Hs5k=MllsaEJ_v_F&IZNA@-39G*s<8 z5Cn;9lAc3c$0Qg$OJLz44r&2EBBWL#K{@+GCc6Hhj=B>LhJ+X;al)kkuEY+JIjZup zGqGy3-p|$tJugj^E`%7TntN>0-$TsEMkH;7m=9s#fA#p!8gLMT5JzU%!$v2ZY;sep zL5@OgXZb^n6vHtCri@3!AVQpgYkkoL4-r=Pt>ILK0Hf15V|i19JDI1*CvaYJn{DNk zP{{o3vZB*T6%<323C*zrIOr5^0}{WypwgH{*`b|_S^@E*-++O1Yh`_~*tN;f$&s_4 zL(=zBe=Z;H*}xY&lniwv&8Q`8i5hAB)eVq!V{&L8Cga&%p=>)8`!b|K!3>7@V7Cp4 zBJl;Ev$rKIMa6ji*&;A#I67rmhMdanA!v-sC!XXgMJiD68pt zR{w#b>n0V7Ya_Np>jgV`0vPa{vMwvuh^?`?e^JUGL!>Pq*=_JqlUIR7&!o(6?scs( z9q6j1{QDxW#RjPutFQ=rEpgFuWq1Nhv2Ub>$-o?r*u(xpDmyKTeVvN6r5F!tysN$; zBu?TM)S8P9jtkq$q4xMuXZdVaIY*9L8PSQ5+|{pOaOf!Wgd$`{xgz7t8fFycpBUw?1~)4`M{$D)7Ol^mqJoz@nY@<(|Psrmns-4S{O#S(P}~Ah2QOxbz-SN}FggVbow8G%690 zNo+aDo=m3pT_pC*b^xtzhs+Y;O&DE>EG!qp6WESbe(MIVrSgrbj`o5_SU!<`e|W3! z#nI`{JWeGxV=uE&1vIvw-3*3wnU6~ zwVfY(A9pz$6YgpaT;YaRCnIgIFQ9rKnzmAP%u=84AzJ8Ac0JT#=()lVTntLPJuDlXE?bQA z0c7{HroO@DpQuI!3EBaoYk7l1kVfPiY_J075j|2>ARGKCy)$SZ-?DCuY_QHh*DP-k z;=5R z)WGUX`)7S(_#5oGH4jK;gOk*6XMp*O`~e>gg>w@UhA7kDf|!b0aD-_Rmb3vk2tWYw z4`hu$6l>o>SN>}_o>tQk4o;8hpjUDMJ!RebmiFAVzrajW71cqye?=9G)(^@1-gSZ1 zVRaEUO1Xk?%7}_ z3A3_`CoLwBSZ=GGN+GXQvua!t)e6tzfrx$7|DTcJJmfeZ#NKV1s>-Qwh%!8QCD^J# z_bZJ5)6lb?BTAE8eEd6(;u%6Ov;N z4?+=F&<9{v^!1t29cs`HY4=Q@JHnHdJz#%X)kR-66fMN$!zLi4V*_tfW8HML8xIf8A}Izr|xY&3hM18hIin zsEsLtCf3*z>!M4Qfy_5S#=Nuw_^`d|FQ5{lqXn>0FCkX`b;ZC31eiBDPU$e37QpIT zYGk8M-o@CcRkIGG0=Vq7*BPqULx34#{o=kDA|M3VmZIuSD}b}+EFxC+t5E<)E8y9y zBM}^0TM%ene|i>4j%$6E9j0Ok~x%v|5+RY3>o89S@e1pz}V4em;QbP4~Sz9 zOxCKYP02bun;B26?I)o%bWVl!BPFZGUxFM0xC{@HCvH{m;oNZCK*%ignde`|>%Ot< zXzuPHW>$EBjDWcpf6zJw30x=yCtAFg;cYbR8gxH2e@}>c5BmHE9Q{uH+|_PCXH-0? z-d~v}r|$SOoe<~UPIVB7CXY#WnW1WUXj;c>wjqiE{;{@*@J1#8HD#n0!Rk7nyOwxG z-BtLI4xNnYMs%!;I2R~?oFeKjCC3L+;gz-6i~7SO_)*L#>r?!tee1=v>ihzYi&W?l zNVv-^e>nE9R4R2HT2?z3>5=nVf5Z!lbm@jL+wox;a@18!KE!~%)dOSto%k#%Tp+sV z=SNIg=9c9zTx*A1C|B~IruYkW5{HB04kL(k+Y@=*_lIpj*);;8E$16yRwfEM{6StGGW*V zJMNJIsRof+mkSoenc||dVEyV+{yV_r_H5tFw(sKuzA9WB%vs&<>TmKuBS=U`4Ive0 ze`JS@D&V5*i`PeIoQxJbMDQl+#<(1)fW^YgZ#ogo2ouhBqj{Q6dIW)^>Tcfhk{62N z7#wpMXf9Saetv6J6Af)yC*Gb6tV6>o29u0Y>Z%t!M191QooW5yNmy}91~VIt&*f#~ zTBGdFJ6cVEa6Fb6fQX7a=&}Nr9;m3yf8!=%h{dgAea8)OJS;fjKb!o-TnxN4Ms$mq zd?F9L22jYl6Q(V&2QV*VYs8-1xxuOU`T9?mm<9DnS2dX`GA8N7noc$Qe3d3I2K%M- zHQJ}{w?>8Xa?*F-gA(Y71b)6l;YeQ>{j+lE3&#+m0b2?m{=Hq-krzEgeX=ioe`C%y zAoF~e9yx|sBjrML&g?{OU)$YGARyX+ptuq|I7kKKt0*gAmYht$bbCLn+J2VA?g60| zY9`~yNuH4Ne5*OkC>bnM&JeQGY9`-SX%KHhZU4_DC_A}g!-~>k`v4hovT)E5*wnd%7HL6T_e<_4Goxwh} zd$&|WT|1&vJWzu53;~+TtY;@WH_&`Sl!<>z$PxywLD&x%_l@ACjEw*ti%j(MdnopZ zDp*jCxR16;$wMQ9PJS={BFtSnhGKrRw~1tpI-{vbinbE~9Rl-bX4?5wmM5MwVdW$Z zaKvqN0tBi~-;UnG z`ck5Oh3&b%#vXsCN3^f_X;Q+#uJ2nWq;FV)H4%q^X(OKc;!lSh*B5O{+T{(k;)}Sx z`Wn{L5f6@cZAbk2hPCipSQ?j0X8-l|>AlF5*OjjCB|$)!av;qAe=L~_fs)5S?U;zv zkRWCvOv^JM+d2KVY3B94DiOR0rm)Hfr-VM5Ye#T&;fjdI||lhr$luCJg=3f2trq3DhY#Xxc7$KXI)1;?A+}3=U3rVH8SFA!XFyA~{j21m#|W z9b{unE2=>k;zy;*wHCfY0eeAxeE?JLnJYY;l?~68itNE<8Pm!kTiK3&kg=?$>I|Xn zn-1vzseA}tOrd#cnC1FrtoKtq~Tc?HTIY3#qO|ZC2AiV0uo~P6)jKG|9_UKl9P%tutnjmCAiarG4^MmbK})4f1~rNxDsR5N^R%k$Dyb*MnqUq z^#X3;RknA+Ay~K|wz_nL90Y~kx{#E1)Tdxb1$80!7e$*fRkqUGUI-rdFfO9RPV!V1 z_>lRS_1G`Nu#aL~JH+v+X%fZXvL?AvD3hW{GnQeFspEQ?;S8X4of>cmAr&6fwxRtT zHC%Zoe}pD1Pv)L)8ia*?N)2M8+E{JZOOyA>zx9vG4W;63fsivRz36Th*%7l zGi#qok!b=I%|*pBCFRjqSldk7mRMhR%yOXOFo`(B3^3%@IK1WHn<5n&QjxO|)9ZH> ze^$ExbE@5#C$^W!r6f?d1-DL)t-Jq~j|a=$jN9C=x@*Z-sBEyq3p8lZV*PUQIi)uK zCV`iWySy(VcWg#hV=|lw!yIL3+xE?VmWqr8OvSs_~7fVVI+0M;sW5^NH#EH zjDUtUvfPXG5vNYN0m|{z>G%Rg`89|Kf0H9NT%i z0B=K?&_X>$ID;mUIKyJNuE&AtDnKe)gnl5 z(=`O0gvelcnqmw3)IZs#8hSvdc4Wg81&27i^*X{08z<+^wNLS^edS+YjPxB)_%UPd_J>PL-M04J%D5S%$Uf92Tfqa(91Z%}ncrWKloi*mKy0%X;3<$??#Pa_#z za~u{^!7{+cM7nP(}29MKo1J#)rqzZ@1DJ$k;f4v8<_Nrmk+uPxdKE z>SB06^hE^>K`S@lD~m+e>z8EHDH^f;ZN|&9E;ceww+#HZ7N7j&#Fy9g&l|V7HSKz1Z7CAfm)*`LVR9q+y9xI z6nzNEhiesc?$v)CMOZ3$2{KyR2Pf;F(07-B2`EClDYf-Ne?0^O8931eIZJ`V%hmrH zC!~rtbdF{fA775|c=!N4v66tBxiG^6K=_L{Q>W&-k$wGl5=8i`s(>#@=PtCwH^W zLP`ej?1 z(DM+aJ{7JAK!%1~j)ZwysmHt!mkH(pAx$&NN1VR|e~VfpksBnZgpFu}HQI9yG+pb{ zO!9TZVM*lmDC% z*ux^9yxv1H>Y*$SRURosI|eAto*?nrxuHp-9rm#@iap@wyy!>XGsfW2`QHucTiVEW z4@&27f&&t&r%LykG^E ze`40-u1TVa4%qEZ`-*~p38|`gk!kMyPno2m!k6e-paHb!&}8*;Y2}OSt)2`ILu>08UNsCJipC zQN@85chJN_3_I*Tswhj2zAzJaXV>QD>wRHMl2jChLg1<$nISlD0tj5l1P=k|mmWmM zkX5;~ydDOK_qd`nRFyzXTEQVQiHkLwUzYqJu+scD?L@reBT}^{$bkd91`-Dif4D4i zH2be(D9ZjyQ+x9KWZ7J#5za-^U{~-TAjJ6jDp98bK7ee&1vm2cc`J32UQS!1RH@h3 zDq7)Yc&C2Hl?Z*gDVFjHk-#qe_W2++R(QliY{!5oH*(>sh^1XK}=1;5W!LR6*~aqHY@qbh%OTsi?I;K&uE<)2aXS* zBJNxPgW-)sIvlTX#s$DLCwdN2v};wHU;&T-s~}L}kinptkGl-d5wydke*tH}e=n?i z^8{mhAp=ZWLFkiizgu+r9z&nCUmKuqz4laenS7XHq}mOjrnp5$kTvV6)qRv@w>~VI zKaZ$9&)aV>6eweTshG-r1@OibJqE`_`~^!v`yYc;Y7AfD<^wKlM+diw&a0y$_21g$6k1Mu^eKT zB=QQMqbKRx;r*0w$9vYd$42h;aoRF#0yf8BQCV}UJPZa0_*gS|e^MJKX5IN4ADA>n zI}ybgHP{8I7h;X~JrQT6B_uq$`MVp)f3zcFR?o{%dj!|-@#$@re-!MIkkY<^o8<`7 ztHBxmA(|*c6pr5DIJrNyj1`=!nxjP9&F2zEH1SLi#Bpr^qi1s9sch(Umi4rbqZm>d zbd-1eq6=U*imB!(e@w)!1)cGK5*TW-9gn^!Nu=DO;|3VgS6}_q3M>ZlZ>Ei@(5J(h zp?RP-lRkl9hZ;%#xX#rAzPCum;|^438Y+1Jc)Ukf^BN8mRRhj|s)s(9DS?K%PzEso zDcGL3^89cD>l6~o)_fNhpyef(D=`x4#&c<4s*Nx7p*KG5kRSCpam77$y`q36{@Dxi&i(x+JYC40&xJ z2QDw&Buh6HEC3*bofOS9u@I2VK9Spm5kx=*boc_ff~rx<*IOJO8c0z6tZjmC2oxg? zrnB~}(3x6Se;K{#?RnG$yykTQNR8@Z*k|ogb+14WMs9;C*7Ha=2G@KNjvIFRI!iCc zD)y;+6ZalEScc#U3Y+8)MqdcQDYT#`^B92zxhoKdQXHCAz(Yu|42>%vu4XXi`*Xz*E*BtcQV+ zxi_bCKpvEzwCgd{r9`e^sE&T7$EyPD))A6VE=f)O0$IuayMe|yxNi;Niv`=G9YzC>U_3^umR?uFM(%sDBP0fJ?v z%cH#Ve<|wE2Y8Q^%cXd(XWlFNbZ$;(nFE?p>Gf2-dXs@+8bGPPO}0T9t4>L(e+_FO zv|Gqcb%c&0;`ZQu;AqF_3#kv2Nub_i0LyI-rasNaY`h3%4lB@9WlmQ1I-~}gbEY6j zOT$O)(i6NGpF}~C?VoK+VWR~_C^VZ4f&BG|e}^8$$%tvQrWp^PcwmNQI1R?O(ZD54 z$Ka$PtzO_lAT5S!Y^A}vHmvO8CGjx!qGE^TDon;aic*Ah8d5l0BMh}2wr25J%)R(2vch;krIXNlhL*eOlr6&W zpC8Q^sT&)FH=jgWjJ_?8|Cu|saWpfEoM7~skw>-Bb^q8=ivZWJVA?JED8zQ}f7;HX zp()Z6)&HEuqV%n@r?YIKl!GSw(C~L(XS2ZwsWD*`g19uQYU|2wSYVL2qAb+mw8J<`^c|8kWpO8fmOyu%0Zj5Hj6r^a+y^I01?EBOByDHD^|pFL|Y9ru{-Pli;?SSV5UuZ zPH%kzNk^S3@(H=bvmPse{`iIyqU!i^tTS69ImyC+2KMvxJ5p#GpR6D6e_vXj1vA$y zSRbS&_8Gc$uIEC_W9^LsE z^rg$j?rH{+;gQ}?7$o~(8`3~H)70{AK}gSV^4s5ov08{S&w<*h-GLZM%=QKop2jUz zaZe>3cGN;B4rosEjI#5Zf9>JZVB2F8(LtSv?MRdN7s=XXn&XDO8S=@eUJu^w9k6Nm!Xwo9R z@ekJVd7gMWQ}NGdoa@<}*rV`A)xq~_0K^Huc_!E%cBULFh40=15Y>{m{5yAMn~;2a zAEuS+naQp!?g8ws$U0~QEaaSmpT+nIyJ}G`;)#k%nx5;Hf9S0J5txC6Zl^#tFoFmz zD%YeyQbP)Z%bQ}XzEv40^57T9@Z1TG6fr4)n`h)`LXsXC=8p{tZGov>tV3RAF=d*F zL|C5cusw)c|EeRB#_8sl8myK>6&iyh&y+1SCs=`Nhi*Nid^#AE_O7&W{6-Dnnqwrg{}=(W0>tj%(FXIlU3sUWsxCaTj3R%N+4% zrYB~BHKD;`v63L|YojIMF1B2*4uT;N@pfW>Vk8!FD^XTc>>dFEv3CpTu0*&C8NkdK z{660ff9b=a4(P}{gOa$6L9@k{%KQdH@*SUCg%jZfEi+pe;)^^seEGQ~7>Gb6D;ZRZ zBmM%omIq6K>NO4>d6%N6&L42-7n{D@fgLODo-3S)Mo=Pb< z<#GF3B1h^df2mkG4I-h=d!dkZ(#JNa)j^|^f0Ve5+#YR2avfvf!olRAH+>Be*tyki z9&Y*g`k~d_;dh6*?$@DW-?JBW$8vw3X?2o~uPmAHBPGkO(bx|a8(l8V&lxnV?O+Ns z>pWnc4wIfUW|Gg|8%)Vi>ygP!x6@g@5(m1dm`r`4KgooFS>otFluAptDkeffy=Af0 ze+|uwmgezS%__)xK0jr&qRO(0LA0XwE(eYTFqx@x^v6s|5YR&}lf;SsW+oCK(Md4V z>wBzq=_UEQy;YG^F?*yknYKZCj!birUgZC%=O|W|VYjy{@Z&s}goAb+jCwuXqoaQM zF*69uGmk*{cU}s)lkYknPQ(Vwr5-Rxf7%4}3okWsKe2%mxLR-HE=F z-gcbuH*|cgWS43TBbf&J8#UErn5xr5w~DhOEye2=I$Rw9ll>q~a5|!6L7Y<)-hCvS zU?_-F9$0IQ{Gid}`P?^_`I-gse#xyHft#uNsjV`GNxBXux8}oDsO6R;dSHQE|xJdtu@L76i*)= zI-~?nJb1w=+n{V}0;*E2On9FRC%(&RFi|dG8N8cvsi$DxI<#W56&`}Rf0_{30)hdC z|5H7JrlWcgAZ-5-P-6N!pQYOik3YC0;6O4PheJ%~rHWe8Za@slg2&zIor@sVMtcE) zXwR%hghwH2Tsh)&#CCpvvKEI?)B^-M`@@|i{*uHWyvz66R7|IUgVNAEIlp7VlBd+J z{?Nx*ia*sPD3Z#E{(6u5e!*~(C&0pK2c7}2<_p0o+vjOr~saaJW5 z;>!M_u};^fxSbf2W51cB~GNjk^f!JM~Gb z9lPZI?FuTn5MNh^w}s%FKiLuZ#xF%WH=izb$Rgz>A%pQ!;_{)Pe=})#LexxnTVBy% zlSBL-j2HZ~$rFcK5d!gQY=S&*fSb|F4 zCN(R6v+ERcn7`;2f8q5`Df~bwmEdWF$CKkFpKAytsK=V9>i36<+jtqtj`%)8UPBYZ_cMIyuqx%(?G|zzlGbE`z zj9L7bdn>s6Q>c!VqVh4*o?L}=0;!C-Vc3=vboV{r7KA;1MrqMriqxXZuG;_14ik*bsh(nM|5 z)@2O~!P@PGG?9%#MI0jIGfnEoBWcncSU#lt(O%V4rQFB`j3*=lB)+S(LH*V_f7}DD zrcdn+BsIA%f4Y^*C-|1iBMw#eoJURlE@?V=0WRbK7%+&_nt1dyh3^r9f7>Y&kK09s8aIhqJ24yrZ!>2z zZ$ptIaYJz*!E_2OW;1UKU0Ba>3VEA@`v_ZTqlg>n6!JC_tQ9wYVM!O(+sX^;ZH0-$ z+Y~L8w++Bralj$)Hri<+w^D}F|H>io7N`M?2iA%l0&hEno3L?UvC$=gMl;rmbN>vA z3MGFMfA$5N2jS{88P$UWnf^)3%3WXthkzn(H5207x&Q$N>Ew~eXj!GtpPEXVZv zg3ZN0xt)cP7{G(E>J&Gbz!5hVV_=COh01N>1x7$09vrt(X7!Mp=M@{b5M`u#O0O^2 zP?}6UZlC3p)hTWf((4Ph4}l{FNX?okNo)o#e`jSwEW|EAz*BIIe`FaLl?U`4Na6UA zQCaUmnwd!{5+z9mxzQFiagz)P;noER$c2%(wGyswYe}H7%Vgk4)yTF@l2Ezr)x;kB z^iQs_R`hHZaAx&rRH$*2C{%76Ck}5bbSB=GkZe?_af=j2;wHxuD!0iJD!0XuiYg{t zf8F-U$hM6WdOG(PM&kCFe7uq&pnMiExp@+~-=E!?uUwyw^J`fOWQ1_P1;cVwiRutQz+p5t)fDW+XOOq0Rm$xdYde<3Mk?h>7OJOe=4_$ zuff|;;3mMN0@Odbyh*aLHd{stf=E=%4FbHD4iOj2jS{A z$^sTCRBq$6D%48?jjbjgCjlBCe@CRSeB3k&mD@Cg5|a@Wwo|N<$ylLspao2Bpix13 zh00M>D6det4c4WCjUyH0CX)(syDVUGizSTL7i^|XJW{CK20_7boB1aN-3l`%bmWGHdYAgh!EL-+d2xe|YsPX1p! zWboiuWxs-)Cpi)q5emptf0~QfxX+M3ecElltCCq5a7Z8QWG{Q%e+%}TRT@T)_CrN3 z9N;)0Iz^p1oFW@a$6a9X02LYaq_~rpihP<`XO#Ka<3%3*EAd&Fvzop#^AzveVCt(bME0o_yh$V`y=l9cce&VsG_m%Xf4h{~>n$WRbHv88?zSgJ zTYYR{7a)MXqwPbP*VWB+Kpa+ESpUgN-0aEy1O4b@^&&C;283WV4Rz6Ii3x2<#} zm6Qp}fjR_X_!|Fb~WlcL4%qDZ%oatrY*5 zOt^azimCtKNV_5ATq$QU_V)BS@iF>AaB_$ZCjCM+q{l2(x zAP-fn*hd5;MR-DD@_0vEO%ovCn1sf#^Z*XP=_Ns-c$eu_%6CIBpvWGRXm1hSAEbr2MKJNMk;?goO3%s^D@$UizLZrJZ zv$)a$E}(;#!H<=nZH3WJkvJ3G1qcXEhU9mgNbFySBu*6a6_vEguEhP#$tdG>7?PPe zf2Z(i7}2@gCrpYhGjr7(q{@k8_Id)+SUE(8zoVw8q~Vpp^#h49^EN~Y9PiP~6srkLx&VQ2j0K@Rs-AU^710Tmcj#!rfy0#e61Oq)E|Y4vuWX2(upaem>? zC{Pzan8BP1rhWlbV0i-QS8cRDj6+M*Gue+Cw!M~}0s9cW0BIJpu9F_B#KSYAZqM6{rVTpcom z{HHd+=N;g1idrUd))ZH>{FA~Fp@7^=WLA!vQm6(DljSv5*+*7-83@8*uv}eaXB3qy z%+>cLncqdn!1W7cq`+gLi%G{`k+{wMip>(WPjZ`i1w^oXCl)Go;nQw~e@D`w*}^R0 z_pIN>!D=NkmCu+YGnZ2ymB&ah$Q(fSFc&UxSceN-a8OtN($a|i^z?QF8aKXa0mzLf z%ST5$q{-uyO?MGxK?zd4J z;E=}38R>?}3dnbNL3_+$f5yEcI&j)<^o7aLzilUFtac1Rp^|10-n~INBvU0lKGw!j zYS^Ahj3Bi6M)Tk-p`!A_%TYmn`|vJ6U?!v>jByhYN^+YothbE@me^q30wVRh3gg^e znSc&{eGp{-xSWy{JlZN`oq4MhF=-2|6@QMy$Q-d(QYCdZi|iRke^BDG8D?)+g@QP2 z2Z+nb$w>Wy%8EZ?^ZJ?YaW6KWb*rIByIWF)#GF~}9S}chB~-b-Ev!?|>4Rw1%O$O- zG&*uW*p3O&j*m9LTT`}CxDBuS$x7T^fIt@@V7?r=8Hq7ft}hKGpCZAfp=9ulh_=>< zN^RIs?ItPXDVCYTe<_wJMdg{pDary1&O>(Dz*ZG$cT4c@_UQ)JD#5#(<*NnP#Yhi- z=OahONUwkmiPsS%bKH!{cbQYaiww^iI>n~^!)-|;R?boN!l&Je?}aK8 zr3(MVzoY(zDi1Qur?!$$k*gOuRjQ4~9yuz;9LZcUO}f*9e}OiKb9VI!i)YR&H4tBj z1fg9^ytS^k9!Wc57|qL3xtuD=jI6?7qP=peiM4>RO?#?7Cf(&9?f@_E(HoOhNh??v z>yrM4cTqa93;AhZ>g8mM8opk1NhsCW zFr2n|F~Q_J+TJ08^?{F^H$JIJKMV(07r=D&e+O9i89CYqn(wSWn6Xg3Nb*B70d%DDqy5r_)NUDD~}I<|Ppr${TcKg5l;7a&j$w5Ldz zxSieZ4RTbpKw75?1-T<8Dm~cGr1|0zhKMaQb8+-Y+EtM%4?*zo!&5^mX^t>OCCwmV ze|}frHdUUQ)5jCur?qy>aVtEnq!+&{9^IRVROvQW#0&D@B2_L~bW{%a7RXuhutl>0 z9?G0*(&tNq^@7%L$R&*!dEztf4a%jqk)vW_n_RDrn^WW%2Z4W|qaq^y;Xc&5!zuQ9 zBBpt8#z!0AaQ}#4{X4te9Mhgesj@Jze>oj4L6s;NA|`W?D)*tlXII0WHdXpC^tu6- znza9rAYYg!ROuqROW;DOX2GSr-f$dJWr9W$NL}xAO4&i+U@XobKJzqjfVBoWDoQx> z?~Tr7+=&OwglI*C1>*i9r%DMLdVSLH?p`D=Xm5}hGuQDCVch{anWCNIm?{$>e+Pko zO*(E+GC0Ma>9hy(Wr!`T`P;*pt6Xe~G(0A(-EXa9sMMJ=M3d{YZ-{9goDovJe)#a& zKwEH~%*cZhMAzA6+y+A$N+H@i^p46OAyVaAqnRu=ubYj6yHnEI=qumyD`|wkBUnOg z+@IjxwDm#YmBIA~d@>;#WO&xye`sO6ZVG4vhLwZBYc=*19Wl*=AHIV}(re_9Dow*8 z)jrlP`8{;V@OE@Qh&C@Ql|KqERN0yaxugvqN5xtPqKOt`<%WM?4EQ2}au5)zr_iXs zCm6G<(JeFcS&cmjCr8D@DHfSqcR{UtPn&QxhQ%&u<1#;q_fe`trmOp|5XS=(-KBYO#02!Zr$C?_e*_L6`a9a{M(TPZ zHi{!TCSUL|`BK8>b$^MBn@})pcLPB*PI-?Gc_|)!y~wFDeym-?Nuz34E!Ui&yImavos;(`$zaE^*y6$wI{af%0H?GzPn zt?LW(f_BZ0K%CZbRNNKD@7#f-A|s}GaL0*j)g$SJ2AsKfsGVZzIUJqfMmsSWZH8Id zq)G-j+MoFM$9oz`HIOsJ!MbRHd}Pe7)^HdHa&*fj?bsKze@hyn*I!6yv{w#e(rKdw z@^hfCd?mafZr~J7_d#^(c%jO}$U4QzrkZq2@g5z_%r#%(3Xh~81saWZCQy|x^rOQW z?L(_Tg*N9AOPu9;!nP<>kC{6OF6;F#*(Y0;+U2L%{ElaIl zqs5TgZGjU`e(;l3GHyxt?v^zqd&5GtiC$n%m69UruAjnSqODN700A-+Gg80f7+oKp zagwrfKq-FWAyptLudgZ*=Bb$21qgHj0t0y#+96u0fBZ}dY&$D*s+1&zBKDbBi~rhz zvd6eq*Egu!s|yh50t5)GkED2*481;38L7|4)D`Nf+$Dp>Wrd^>yGknxTqdX5U4Xj) zf$;z%!kJGZo|o@P>-qvz=HlB?8-LG!?RKRuaS65@{wFWy;9HNRy8wa9W?}ivII;st z8S>M?f5QjN#kXLf$c}9UzgJW*%X`}TB2oV_={O^qxkgq~zvVhzm;F~#dKCp~d;Z}1 z?WU&EgA0t>9}ISgh}okc|2kPP5NW*a<4C|wMJ?pU@unHvMg&l3<0Jk#CE;Ry;<9_0 zWDkM0;_phlN3X>n#8tM1b!xYy8R-H9ESrmef5*ifw@h}5%NPhE``TP8@Yupq;9u-f zzYV+5UP%O#MIZdEA&YFu8(aB^$BI88vHczZ)``CWX2qXV2vGTAJga>iUAdOXV)J?z ztEr!AA+m1^>dHF|uedBD2iJF@0?0mGpiEynPBd5-R6%IFp$gHWfdu)(4^pKGQX;pp ze}#VA{{g}+4r#oNRhq%AP#_cBXwN){Q*19QSZj}gZVm-%Uk;Z7_t?I2)YvL%_Qbhc zH3yPXE_7LQmWJsWU4Q_M&;jwjUHnfH^WJXZ7dTCYg17(#tCWz|hUnNw(TpxYVCEq~ zng_=?2qHt7r} znPV3qU_o`)4a11KVhzvF&7hUb`8D0wV2fJ-e2J5 zKx8u#`)opDe)1rx{Lc{Xj`_BvVHhkf@M;u-JYhElaYYv|JYZ<$E z4Ted`UBCt}ht%Uqgl^7rVT*^vP!0n7&_i+@?U zinc6$#U+_(RsO)jQ$KWVsSmbR7LZSB1k{!k)|D3YH}Pqrf!anNyeI8(&tebcoY`!K zjyC8urs?vT$O;YCr+9$1!+$+-Aa7_s?Iwv*rRw?YW73bvZg)emnw3zuvGPn?i23h8 zQhZE>80{JDMEw^FHVOzauM#lhCd6^-6D*Xz@(99%TvmX@oSCQimg^<^SWM=B)=5R1 z;+Xe-xFiHQ!Hu?OWk-b4Sh*){lYgPgM%r;H?MaBmFv1wO2dKksfPce%t-|(pmV8HB z1!FMp=|s$5%5mkPh9EZ8q+3MzdjsKcRqoh>iDXAun@FPt;-`i-er6XSAVN4+eImb( z7@ZiDw&no69N`AGm4C}f!6AL9x|!R|H3&BKVy{0`ZsYsJt`0DwlZy<6$yE_K_JZE+OkS^VxS;Ly>li@oa$eiL88dM&&at zCL@)ropz1LuwFx-af6YyuiST5rJ1PRkV*ya?Si`pVq@>F0Dnn*7@>RJizBRQB!s1m zpqhRip0H2Kb6w+0*p4y&n7{hHFk3p(M2B90(KfKU>%%Hi{JoPQ`7icsH${-Jl(Ipx(v?DE zZQRk=Y>YFJeOUV9$FO%z^8> zJ}8KHd#;qP?xFVYmC;Tgl9^k64fQt~(gg^V6O`=8{a}3Be@v*ifMrVaV)uYYwze#7 zRCFN`>#)O(*h`8lc1W0zl!pvO>@<_YKg%-U|J4#?e^G6zUs?=aiOM(b04M6=%TwQE|h3M0gG^dgaX{RFm{B6P(N`Xt9;?s_LVJBz;#M3uD#D1)-RkGm?nIanX^U~g znl@D$ywQg6f?R<(oHLHfJ*`NpIemPiQGW*($@G;g(%6+a z1b?N+te4NEe=9X8G zR9Qs?>9VR)U9IHbx2II5{; z1Dtc(Q#?FA5t9xLtkoBbjfA`ZCnDMgaM74~LL>-5dKmL)^J3C!om9^&nykuA^oH2UJ)Axk|3TcXISdx{w~iOSp0Haf3KT^TUCBJgh1X zh$~hU$f}-(#AdWGvk$G~A0wnH5CxO#?1&ayeYS;lgT#@Z1L7fQP#2Za?wnPjAa9t7 z*ZqXVXfqruag(5NhcQ_g?ajLYfqxa@N8Q1pzT>*hT;ce}O_|r3{~1iQ4?5v)$9I7B zf%6Ux);mQ@`#aiZhv9W^zEI`*Sk<0zH|$X%3?2npKDybxP$hyT3LtaQ)J{aS&9VY6 z9^Je|+I>if1fhZlqL1{DDi5!XCsq=jqN7EQWSA&bs*8rod62sZkf$Lbfq#6v<0&4@ z7Dm#&hLxH5Nklu(ISm)f_^q*U?CuDj5RR zF{VnABbT$QTX*$34}B)xHp1Tz;Muv1+t7L>jeb58Yf8eEua(_yo+3`4Nke-0d*@SI zk&zdm z4bcktv1(|GaSO}~_j*sjJ;DNUMd;KnPA=Fc-PnUvDRSBk`dq*osN7Y3 zOge^{5SSfziGRDN?5d;-DMc-C zu@!_`+-TQO?J0hjcDGxs-Hy{|+`Kn_PcOUOh%wR=qs_Q%lkSv?jc467?@&8upBZp>vc*KH|CsdYBRT~pR2lb;QLLwvLW9*YH`tr|MX?99^?bpZnXUA@djV|(XrMh7O^YJV7Occjr*9+RMPf7qv$ ztc?V!@-o4w)!4Jqsj0m7)oQGw#7KHYz3!~jj)+tglzY{>Al4dm# z(blEd3Lb>c4S%5F=>}?d!a4~B?IulkmmdBIYj1&^Q<|`Le^xH(0GgF*kbk%*i-fx$CmO6>M8oT)h6d}HBz1jz{9UYIO`^Xl z+)}+<(tn1MqoUhr{LZ#ux{$& z?TmB7m9=wYt?N4TbWvbOAg;*;`WEKRDW2?S(tqNfxTC#NP4j|wNf?_ni|EL$U|qJd z68B={vfI60o?xO4>+tu*=(iS#UsAH)KNlM}tQscnX#2EHl?sEdfZU%*m1{oZVsyjq z^~3BmKG-o;zUW5OT4+WfkLd7shGCE@MRQa>x;i6Oe)+JlJ9{0mauB#07Tk@hF7VpL zlYeNZ8nQGwd|IhRpk@Qy#XXYV5f+FO7+~QuUo{pyf4C`Y==JlHwi^+4qaD%~4KLS(!|?Z$ z0sgH5%9NF)@~@zljM>#NnYOS#l#Fq~l7Cgg78We&$VL95-Rp^U{rwFqqn&uPQdo^8 zc#n>56RLE@jsph?Lfh=r)YM$W5VVD%!x?Rr9aCi=$tR~YDS3h&fw| zT(``8SUCtBD7jHoz60bN8Wz@j7=vRhK^-b=@#7It&>|D`rdwr3az3$D4JKF7MlPV{Y1{?-R z%##8F#=}gPxSW6-!g~yLesVhOapHukA)_+t*^OAG23lMNQ?}t++rm@4|cD}m+0bQ15IhHb`ySM=& zEK^7;m<}9e()1dC-D(8i|tjcVL5JN$n(y7E> zZEL+Aa3pfbrUE-1dmUI$r4u8}zJ%c8~4KFEG{f@TR z9gw>SvdET4nVD--L_GX(>q#4FOZ_3)_9OZhG}{3kIS2eXV16G-4}6BxQx*#87_Md| z&8o44!^T1Iw7AgzEF!(IkOd*~+ccTD#twv=tRjN-Y$1zmPGWR@){HgLua*mP8fIXB zR_YX&6v-^w1%JejzX=KCgc!8)oFP>yOOb%_kJbm#G?Byd=_D0xkfun$D6}p>Krj)M zxWFLUdnJIxhZ`>;49WhcRjF4o0H#L{m?W|y}NnPh9N5x8JCBfRo$#D?XfHMcz0Y_L6Z>{TQ zLZl587_+No7Y9LMUeFplW1RTPU*-?@IqH<6^1@fF=;wEL?f z?LIfz?|bC+PY)Tsy85g0k%4!|i%7SQzwjn7zQckN`2nXMd z9K!Dmi|wo;5%VvhGTNr0Eopc%O3KPWX6ECnKsl&2-BLM4<&sbEvPwBCEe>AhmZ<$8 zbg#cGgZRTCsifo9>V?LuvooT&$W8UUVt-!1!O`mC0J4wFgZR(N zgrwA&!e-cjS#zdmh2Rl;Y9K~8+N0eq9E4cd{-sCZX99|Y*K2{ z>ed4B@6#?$$A?t;X^KiDIRG0-Ax4D+%70bbmmoG;tHxWJR*lb)Rf4BJCo`>l$7w*c zJ1}7RnE*w(MiQ)9tC9bhR-0(f+h~D!=L=Bzj8yWw+FzBYVK{TzW?=s35*ncf8 zrDV~^Jv*I5oXi9ATCAk~bb=1u&Xh9g^5g9%k) zQf}`vjAlL;dfm`Fpw))95+DQ%mL&ka9F^68Z0#h9bs=*_tb^OyCM}s42j60y;&OHM z!M_Y(>Ng@E(OyrVkH;gINfcnVM1Ot=3q^LhHO9lzfuz)gPzNs|xcGmOzrfYY*Y40& zVfmA1eR)=vEW+PYM+@tJ+NSrk;Y8fb@9Rr~Oxmn$Q|NR7QC0|sJn z2C$fq&B}C*RTcZZ9EexLRai)Di3jk6uK!2}lCsdQydG~h*LPG-qD@YN$YB_yN{fk|aa4(08SVGc zSRE>rlJR=Wkqri%!GC~r?(xEERg+eY!(!Ed;b{>LqYDsd!5U?7sQ|Jks4K6lBA-gR z**0R|7#pv%h%MwUk0fr%L{Q@IL8cWtLF&U{=kCesS;~UQweV1Tu|*}_xNs`(Y@gzN zVi5CBVn)5A@`0D5a#poDgb9$h+JoFgx0OruLSsz&4F_Wc!he7%edVOAFCupl9gvd@ zR!HNeg^{>DWHNB8c_q1Vr9-l}HzTxtl2L%XwfP`dMYV~Rp-$8vtT;<)!Mriw1qfI^ z%Jd+?Ebw-Q7;SjAA==U6Mtim~$sWcC8T`XAkd$)mwes6;f%s^Km7ZZ3F(Y-xQPYqp zRa)lE%nhBI%70@e(HS}_^WqXAbi^rDK>TAD8Vw0TGGKNnEzhL2-o-oGB|KoD6ki#j z{Kr10N||BMeitxgufs|Mir-u)h|^Rb(N1FxQ-djBe3v%7zE%#Bk`^0~J*vgn+w~HO z@7is_!}2o8`7%|fHbll$DUVc1>i1WFK8S{>P9N{ElYeMGJ|xK12@TdRN_2`{fB*^x zdDjtP{%PjlYY&6iC8mM>QNt@Px2AP{*$M_Z$6)b4av0?o_(mmwIr(YCLa=tbUNu-; zb`{IZ9bxEoupC$JL22ZKR?;a6)^3&b?ru4lR%s%8d)CouejX4zS6WsCbB_I>E)WX!}vkMLv8p(LjBhZN?bAz;=guT zr6fNc^A{K`@si+eqMCwr4=>vIeI>!#$-<8|f`1)>xT9b~B_NsKQ`PB{aAaQZE)~2v zS8z94aXFAlvn|AEi&XF0z5e)+CIXB((73_&A@RB%txgf{9^|G!!;|6?xkR1psJxVn z`m$lAu>p^KmZPR9!u<~sRb$i!KeKY*FdK-(9*c-z4fl%5S>KklYQN%=GLZ6m<)KOa z(0}lV`B27kl=#art^79nqYay}K>VecKOXa9nn{V;v5mx}E#`wQ~4~pini)_#iih^p?()25aT$+ z9@`{)m+@?XGiajc)q{wqz%MFK{gi#hWq(Go`e?ZFmuO^pMM5NQfoQ&X7e=A^MNMT7 zsq&FxMycN)r_c1xUJtjwDn~V+c5BkNaXy%F6HOf6R_RQ5kMXZ$ZC+3zk< z3B)6AX67uFAbUX}RVfE44~V}oRP7wwqyvnb-{DSz^?@eBI$pezvNQeBmKj`@_kTi^ z>1C}`yD6T?z7)E2+@Ey%c!d(Kd?iUBH!+@dqohyENN29f|JIGzken*xIWu$LIeq-F zA)WX-qC&8CJ8h~=bQoTD6ildc44LC5jB~4@!8)WcB-`qEv__pMI|zIXPXm~dqMLnE z2)_zK-2#P7g;@icA6C`1h692~Bn}LMD2jv_4B{Y&fjEdM#~@1s09l?D z&?K9}%Ds`-qP_x-IHLf2y>VK&1 z(*r%JX5Z$vjj(+z;gKFd-A@nT_0MUSdee=f_y#d;sYNF}@D2yXF+Dxd6}$=$(gW)1 za&@$bN19I$_~r&7ri>y~v%+1b&Dx9iv3T4{<^!h(z9Yiyhc3(00}VtQj4!T*7Lo$j z(*r$<3_8LFF(B1L7XU35SAU0+BDLFsBqb8$Jewa++Kh_^xBRIh;Je0Ds;tSdF*CmP zm?O4tag8`=>h5-Bljj80c3l8C<0GulDp9{J?o__$4A+0;^6-UHtW_NQMVyofwP*d% zYLbCwu>*Zw6pkRMNrm}=H=F(`bQp`m0Hi0B_?r6(0rG72Yaa>&@_!Eyd%yDorZxL; zs|yu6FFD|+@8PP?r9jSBuevrW4Cut7a7zK)DmF)C{^!Wk_cPp@`N=n{1q?9Ome&wc z3L6g>(3ld zvlk+>+}5P!VkfLt6MvCVMe{#c0%6L095YTCa=K8QdLM?QCMm<~9~Kf&0@NR29Zk|C zWV97Xf)4eupNKkr8;58fybPO@n}}S9s2UfUtkun`l3GG$cdv!Ien?_L0Fmwc*k(a4 zVr9(q6?NiHMZhmZ!VQiGZ}(skLcn7pviQegE5d*!#q8t*w|@vHiDREO(7FH*p^1g- zi_VU-vm4>CE8C*e()an3@^T6f3J^ZXnnFo8{vi%h2W!=GJ^>V%z&5=Qf!4!W(BMGt zf^6KpW9}?++?WoP?2>1J=bTMdy+9GfV_GNr+m8mDW4w4U(qT zGCO!3t+)z`amArW_@>K8l(}xh4!t%G7tQP4D3gq?0u?e(pbZxvM@&F*#|;{*URbuc z;Yy9)#Vta;hpKQ}m|VEsyLnl&xZwvsXrPlm8yae8!+&JhJOVS^CsJ7*MXZ~~`ptiV z5e*3ek%$B|(0LfpZ-)W@!ib-46ZXq+@!2v_NIp^a%b?foPqk1?=~fL^2YCWQYX~S7 zBw)9LL+O)e(+j*qsEp zfHf$jntw5uj2zH_N{eiUi{(}Z+bmF{FGH)PChk~!iQa=UI7znvb}8~sfU_k1x$2F zk+8nBiFs@W#V+dQ`(YOhq)02WNX%S|d(IlqTV@i{ba@iC?Qq*RU6uyz$lTNLuqL9UG%oWrT0k z?!3*EO`>ICn_?G+_+=12hh1Vxu}erP!+%kSU6##%WwnicvY4A`88oA!2XQ#8kpO=8 z|A1K{gKZ?2Fe`pa)ldgK_)h1-EFAMh$nvOzPqH!n* zmfI?@+-WrGTuDd)BZBReQoCP%-Fu>F+EJ{3KIX;w+|~GN+R?0MRt08YfEB?T0e>T* z4h#WHh2tQ0EiBUF?D!BRUz^HSL}N3}j1GKAet(@cmcH0PS)#@+_TMQ{ubCz4O@F>I z_49ZiYOEW=5_Ksh>Vk5xtLaYiQbQfeb?l!d(?zoM4^`l#_74wA?a4-y+8a%a;aZN$ z4u3794^xucVENw9oQZYtsQdh3N`KuxIM8J6cz^0V1*HU|g5>fPq@bNh=P6J>P&@1= zW=xec%Tt^@8E_zSo?_v^G;w(fhaE9T=PCJ(nt0^NbrxU>&b8g}w|W%TGFowk%GFtD z`W(*T_TiEkaVI4rK4m5t$k!@~*rg;^PGWX4n!EE}3Hg4b*!>Iu6TGazB7e||%F-y> zGclz{A^=tF{#`*6WkE3T<2Ff`ewE(S`b~!+ZvEPAu3L51qB`1G#YZ5H*^l7GaKPVRC=sV7}xu3j)XSuHgrz)S&2B`4@MBpLm1%~x38 zKKOC%+Yv#2RoFsx7_@KN+A09*d1^NL^!Wm`H2s%5B&6c}{e< zj#pcAi1jMbsaCz167Bk}837(zJX&WLul(nI(R{Su#6$V~$3bwuEKV5?cq;brUH#EDaLjiIZzeAKS9EYEpaECRncBbo%|OD6swth&do00 zHdP4JGn>`Bn|#upQJHKyFtf>K3TTBYM6{Gke3jU*xSCcRVm47F`-R_Z1+}=nPLJ@u z(!gvQb-San#eYbEK=x^P#rt>kVnzYA9EETz0rbPTH5yxHAB6FWLOl%^yo1XMis73b zcM+qkWLai!V@bf89)x)V9o96QiS2+j^HyLkR~ZA*Nyb%Ly%xVpf6qGG06JiwO!elK z;vuCm2QO({$J`dGiXd6t^VU6SSsGpt8_r$$i!O~K_1>37NLfW+9r(}8Y-$7P_i>m%O~uqPH`k2OM&?EFE-VNJ!P%7g?(&O_t@!#Jvt?)?uU4fwju8E zDj-@ofZLE4Z4#QY346o|s#_RrTpt98$4F(5Wq-E1&}7`nKkUJv7)Jo`<0jUUe+($0 zuCV^C$E4$EB9K9n3+0{+d+@_`7SX+uVEt>?Qe~d>0DRt)1pLb%VV$K4=7G!$&?rJ^ zkJnIH!(k%(WE0y9yu<&;#fHMqWxhs1l_uy#K(QyJjnRb@L22kIXe^;o!2a2;hG9ru zyMLqBv#X6FJwCIbHC1C2FhEql-O0{Gl3H`)cZ-5BTJKOs5!~2L2F~_YQ8o(u;_6c& zBrgiTT4MmH`6Xfw&_3Igg3RC%Pudw=y(0d5Ez^_IF_fAyFEq2rgxrF%$62(PM3H|*wsxPeuPHhEqND>U^@*glqx4SeNzA(RbLj@*l2F%W2;=OBR(SR}6xI zuNA|_8$X3$b~Oq??A_83St&N==tq}B=!A3z0Hsze#vZ(*UjjLtOeoVC7?&)pvu?X) zy>j@hwy-+Fe4yo2&4ls@%d4^DcoIRZlWjzG9p z&QYKD@K1GkDH&&={Ml_tZBR43aaM`#UI-0X;_SwJO5(=>_1Rgha}Q37vu!cyL4m0m zcB%PnI9o#gn|6P;+?p9@obBzPh~zp`0B3NYlbVsZWMFkT6DTzrTYqZzW@~X~=@S8^ z-y4!tg%6JB1P6R?5sov<@!2K==MZPAxlPg?*g;2f-N2Dd)sv}?kF!e)>v!fSEO7~~ zNOu^$MmU+Ls%9hmwQCz^E+4tA+5F|G>60bktSo3fEpJTo0cCIoCH{s@9ZT@X$P!Ad z`b3T;7=Sb6p)HW@GJnDT_5hq2e^19cmdc`%XaRK15?vA?&c>u_H9(65nPeY+rA^3Ba)0`qj0^~}JJENR0XCJ! zcCASM%%O#`i(H1u;7%lg&8G3hP&@JHP8i>?gJ2BEL}V1vDjx;p1~-FxV6$}x*05&G zBm<8(B|+hoVIV4L#Bp@us|x5X(g~>G`>KNYeliTkS!1PpT8)Y4X98Nf1fp0KUP4bR zIJfZCRpF-7Tz@XO#aXl|w8$bXfys<438O6Hm1KM1SOv1x1ZF(K5b@99KXn%5RKa z$`}9XTSC2BI!MGAiHDOrE(7ykt)bm)xGN2AgMZGrIu(#uiv}F|nR3?UTGl>4KOepQEIy;HbtCCw`N~~X=+$AzQh?oJ_gD@@PaedHM=G_yKF^HKnqc` zq@j8SU+dA2(S(W#H;*DX%)yx-=A=)#iEH(4d?b7m=`T zA{i)5SR@srk6CSzTb@uOZqOYZ+hXO?Yvzah9G`QEA%IXr`c~Szd?-LP##Ad*X4IMHDrg(hS zCV#t?vGUJ(q_Y)&FRuJo>h~gx2;-+JU(`qcTdKbvWpR<(XzBkWjDGR8^yX$eI5cWCk9f2pGM!$Ck*&uS zu|n4B=g=3+e93^3*m2^RZ7`Jy;0mnpUc$7HvC?@#sr#CLJ5K6+z4%(6p>&oYfi?RD zDKWWd&KVuG+Nc&y+OsFfTN3iFmdPpSaeq#u zDz4Cl{tOr#5%tO2&hHZQbkeA zqF8`6GIRZ?f~i=9!_LK8*g~$dGf9DyjV@z99o(C$IJce3jzl)Pzp=A_lZK7cpyH#1 zOH^&a1v#vWb^YV|qge9tCT z1wi|uk;Iu1i~H5)-&3*Z%^`%Wip>zhGl-oLXX1>k_KOKfRb)jw52XQOeR^nBFde(n zVnm?-^L%*&F^`9;IM71%G=aAaP<{w>ZKYxTGd7~RudF&5+KXanyrHV|}s%O&`5C zAQgYNyGL|I#epT6>QBr^Fk)Y4@)rV-YfNQuU`V~IA}zi<-i|j#xiFkrWA;1WvX;;} z`-Dc-!NG>HBrv?8T}aERnSXNv*s5mBrLR8V;DHX^vXta9Z8*phS1+H4Bo<%vsF?n>EM$|`$sFwJ{ae!iAY za^9pn{Bxzx{vavpK&q(x*#JsaXb?{#8iBuDhZL85GF54Ul@S$OoEDq{KawcvIF< z0`#xJhrmW?mdYeIhb9T7@x5u-r{=ssfRf9p-oct$bDp^iJLbO65=>|=noT3GHiw#D zg5c$Z#ib0*QGFJ=5PwY3x|&9_Jid6ZQRR6CrzRDBgBZN!^HX_3J zErMZ?|G$Q^jTP8%B9{i}&>d4B08Utpi=P|_Y~a@_Ph8*@!8(Br@;Ob73~NY4=@azF zNhrc*ISBd^KCvr!eeGtAe+|e!lX6t#NUB0Tx@ZC$cYC@|$$!w6xAt^H_nx8=_5zjq z&Lbrx&F~Th{JleW;Gohcahux{no6luQXx_Ya_y;FFqiB0Br^cb{@ahDtYzUv4l>uC zqH**(+@A2fug1`O&A=hVG@Hes3~sn!AuIe$bZ7k%O&mQL#sNWk`~IGOt^(+N)z*hMV7NiU=QFS8eFB$K(V$`C>_JF?2FAi+aO8m8lwsTBCfP<%& z9sm@73>5dy|J&a4H^olc#xHNx)Am5}6h|b{|E@43iGR>rlA9!fabS-5x9|aN53B3i zp*`5x0l6i^Uukxwh*fp@Ik9tym=Ih3L~9DT}X_B-$cu zJaec2CWXa(qk_lX1Oty$qf=OD9@GC5-6c(vdgwh%zM!EZR&0+lA2O>08wvMtR{@v1 zNI?j0KBlQT$JjJUILfZcJ%kbZ9Hb_F=CdXpp?^wjLproU^_wPT79gR&rlP68p#YdB znWN+dz&%``<(4Y42N@N_fffWHAMB|35$0wNrEQwTlCC!mUF-I^#9gL_@^YE%V+8h3 z(7pahlX{LSF--#g2P<27va(wh^61>tAp4ktP7?1p*3dp<6)q*Emk+8|0TbW$fPCN{ zsDD@aP1(1T(%2ME>j18JAN?H&Z$i{<>$#?VeUygC#;B&7n)cm=%J2oiw(Nl^#-o7R zdSDA=2x)T-c&@ONC=kW}2eSN}Kmx;lqE1JF#8VUt>J`Hvc%n^mD+5lj16<-W_+2m| zm41MZ2NE`g>`g2I1({{UtS;2xS8%A+i+@+8X{@I_jm*2qRs2TQivE+pH;7HauHPR$ z1D=jt=sWk+u_*$*&OOe&A0kd5$ae1Gq^hEr<%#S8K51Ka1$cT8sJGf^jVZyn_q0v} z=(YE~r62u9$i0Wy8l4w9xT1t8-1|*JG1>{FN;Acc0_lQO33ZKnw}1A& zG8z+R&=$0o_UHM_dR8c2YTI6=gVaDvBHfd(S7yMyrzIkQ3eaJ6qE@Bw-xE_{yXY_< z*#7q<)wtY8aByaAgQ~q#38k*0K)9m8$bG*7N4zOQvvv+X8Fe$r$o-z>zV<^f!J$IOvZ)%@3&46?!Lx&Z5 zr_mnhLEqCl!02cZAk}sN?G`#Ni2f{rmIL5+;Cw2*T#^yFB*t3*8B+D&&&UF|l+=J? z2}k8d2Qg}UTFu{(>{ch^SY&kCR1)B7s-&E^u`1J3FpVmBw@-ozM^r7vp??4~z(sSi zu6Rh*1`iU;$S4yM*9Iqlm8wh2F1#O-(WxMs^^lq1p3+sgOby_7j;NbFk2U97K<;^r zM*#W6V73l+~G=9uLHcX896My$@DL@BW<&BxsygtBwq90Vj9~bS@l%r_V%L1~^e_SHL zCi5j2LzgecQN;I;MniO}C*e9aX*)Ea$)dB!2aW@*;oGD?dnqFkwuDR0U2nm=&XiIC z;IZX@k?$nyX51@#u+joG0U$-u!h*q@9=c5WgN9{rbjtjLz(UpdcYlkM;j>(%3}p!b zN1RBr+0o^n`>f_$yf3j+;?R)Q%J)ZEkKx z-@gJYoLx-B+Akoy{!^C0f(iQ|W?3Cet)!mcPP<{iBw7WuB!H*^>wy5trj+5&v*rE6 zTMz{jd0Vo;6opy+hRohc)dcxLzD$F(C8iSv@UgQ^5ilW?U8&=Qw|@}vW>=0ass#Cj zVzOEFz8!4_O@GRfJS#sao6qrd(R=n%WQ7v0KuHLA(ODVHq}NnpDJ29-8=w5!KXm&P zCrM1;6L$SEux-M$DC6Wg%z|(}xgwQORPO>M>8x&stBYG!>A@t%i;hkL>-^yqe<%H^ zhe30`IG=F<#T5UPKuw&f=a|rcxSZH5u{OVN+k}}%V}D|A`Si%@!6%i_v?GI9*jHk@ z`aCVf7kSopgBVyX6u98Zf%D?I|Fo1+jxRmSYBBG1T)=xYDzs-*@u>hgBJ|56n%K)S zrt;=THShQ-8x{&L5sq2ZN&w!(jSTswe=}{=HW}H;kC9uTjq4RJ8pr7MZ${};3x)Z0 zMHvW#Uw>O79GL65!^N#|+p-5$Xf#d!FepfA;j1L`oLNcFX(h3Z0&kP9pO-gTaL!V6 z^=e}bq0BoUx2eU&!`^hOfRkU&PLMo6xykhCxf3jqvv?^iFXsf%E0>Ua{UHh=?$#$|c9S}z69?F-L=NxRFcVL*) z?9<%4h&wvR8c;5Fj+R2$#aPJWd3&*n=khbNCoa(` z-5*XqehIv}>9JBg zG#pfU-Q~}@Hs+rO z;|)cu^3RvYt~F;G0Kx-+$UkyH`xhk*0DlQNd~^g!%B@i(?j6EU`ZZxUe4o1=cvjA9 zDzR&(IGzaO&>(4TbOpKBeQjJd_7#sb&CP=|8*h7Q!T0Qnsh<#rf&D~hu0e^$) zi{T~m$x&}E&o|9JjX!`A{}l1v*|7s zjTb9Gut_X-{BtyTpi7W&Td7}fWR490{51d9pvArSBIsE-y9z<ngB*xAvHG6vm}#^y`N-*05pTv zU8Mj+3rpS<`ejR;D;<9r5`O|PxU0g^GeJYKU#LTw)s61Lb+_omqsIzEnY)S_Dmq=D zb@W_jlzBtnBcPZ=zind|n548xI~o?vUDuTt^A8X^lhKc&p!_m!>u>{3Fgy!?NGG+1 z+dAP(a>XdoL(hf%`9)C`HDVN&P>N-Ix9Y|U9NJAxs-F|RAb;aD^g|zPrO>Ze zyt$$C$=I3EM-U>Mk>NH#0~qlX#5;@g8o4?3hq(u1SqiqBV_E^=zv5Y(z2g$tPeX4d zacAV#Hk~PigSjL^ywT2ca7kS{T>=bOYUqiJ;!9UDXl;2D3VnT%rI@Ed3|;)%5bm3P zPQ7}|Jd+tpS{42`*ng*)H+eCjV>!f-(DGNP;|sr0K2P4kyjA{W^+)c0Hv*Ku_K$2Dg&Gp{%M|u&9er*ih0OWIrmA3~ znDoFdTz)2oW6J?9mpYC4cO2Wc=7)r(s5RnJt0=R9=AqA?@qdfRi&pzt5?$Z5b&H*0 zW=lWa%d{*T==+p^>SWVV0#rA;NS9Y;@9&qZq8rErPx?=*wt8qIg^djhnh2v}1YUv) zA!D%0H3w&%{vu%>>e1&)<9?)o6Ebzh!G_Ai53JC_1rO{{1m}r5q@2l697a_ut=FRw zKavAWCJ7D3Lx0L&N;9`Qo&zIgS2g7@iyR-RCxO(YySg^U?uq&l?wS67JDURk{{4)n z(J&mNO9h_Bb*1kx7N&mQ-~T4&@a-tWry5$?v|rjTnCM49FYyDQ{w%&Z*m6B512r5g!}kpg3V3z6O8bvJ+Y&v^%Xmh!sJV|zW^qK zmeTd*miCTqR85d=a`+>v%9wxSd+&f zQHL1Bc8#lAw}m<`IitpXC9t$`wHdQ8D*K0tZb_j!RqanP?f`8-lE1JbnrdqV%?El` zTsVLsU;=8Bm4cad2A9kf+9?v_2(c-i@Z8FNJxpf1%;)`vDLj*eEVJ z_DAI6m}6^M31sP_%TTSWS7akQuNEW8vMR^?4LAovSysjoEiAgK>*E7G{8cErxw{&S zVdxN0fk800yvp0wBZj1MW4o&2j&`~HWAc9_14%HfzA`m6FHqHITTCOa&&o{$7McTc z*I2+v2E+E3bYbw>HU&pNM z8OWVIuF1NSC1xi4{ps@_?sUDMP3A_%=imWN9DP!TLSM23xSY}trz!eP=1!mBM?m{} z;l4FwzKMgvrGO>5g_L9Z|IN<`ijuDU4w~w`lx^mlTPZ_bkzB>yD#FWat@Q35EgRtj zn@xLS+@`|-g8HrDfb9!4Fb7;2{Z)T<0brYO02`cp@{Kh5mz+L=exw6bG^4sek)|v} z$2qEcShyIp+j4y6Y06T6h!%b^I7D2e<;7BBxsMl)dd6S%=lHthfs zjwB0Cb!pM9jq7+3X&2ddpvfQ^B(Xww{w&wqICuE?#${n;eYz9S-+8=RLyUif7OqKt zBWg;FU_}EuGUWhBzvF1TRwzsno1^^N!=7aki!OrR68D&ZWXD|XfNw=7E(2^wft`sD zsp)UEM2n32JqeT=IpSSGMmmdlUZc#wD_%6)&Rbs+BAGimm|nYpkeYFjGMH$P0eXsd zC93LN-B;1`dJ4JiNM{E<_E&$ffQ#{tkZyx*sv*XCpD&)vP9GYe?!SjBheA}r4MsTPJe&gCtB36R6Qwu)Dt6@8T z@oL_s%-^y;V-K+5Ck=Pz7XtHZr^;3ESj1)|SLEDI*15|T)aGr%zAzz$U_~f7?d)ZH z$37-|Q+@|oj2|V_v{QdhVEP5=WzB%Hm906 zCyBSor`9Dzfyx>Nr~onhmLf!vb5v9hs-v1)hCytUXa)Epwnl$FjFfw?|H7I-R{Pb! z`N3NK=sO~G9EMYZ0h+~c2d+!wdLr-LZllJ zznUx9+j(sEHSWS+8>d80T4x6<(?Z+2ph4~F$KRm=A5p>GXKwl&%|O1-wPYU~u{6q} z^G0(M28_gV<{y9mTELM3&$p~>aH3;FMFRvLoynfVdLC$uOZpGJH_%cw(;E9x(dIeM%98o323%431*HB&r> zdBYWA8w|$-2OA~vlRY|@PXy9&3+sGPh}eJp$org0SOE;&%|_;T2nD^v zcsxTU{K^i<2hiM=JjdCwn75g4X>wMN6Lil=WxiL`aYQ*ffW9J6w|_o(&CjLh8XN=A z6-3eWPBecevdIm|zg{u!*PqnbH`AyUjIL|kpO35w_1qm)<_zga4p}@*3z|M%O-%wqU$P{+Lt{bO77h22GZwe_$&L|p*&^lB?kp1k#$(Tb zME!pxL6Ha&;2u~Nib2s5ggE91=F z7tKpy5ZGDf+9nY*A@$fW9?->3L*%uW4vv2rYh3a{won`+W(aR$_tMk}#%G;VAe4{3 zVLG(2!^~$0lITCn~6*(i8y$k+AZa8smfO4Dqq#CY3R**yIy|@HCvw zK@`eS4{7^{iL^P3fC7&)Yw|;EgAQyJTn)t1i7`HYDA$zww4dxQ*w2OUKOP?2mY;vg zfdVt(23m_NVQ2{E+X-oR+e)nNDQ0pZ3gTQI&F$ezy16;S%ArDe;k_eu&L#_81&M)4 zvY|;Z7-tYPN@Z^qju}{J!VAey>vXjIF-hqasr}-&u-b&D=ml(tkep1)rc)B^o_q&E zzKwlbh%Fj;*aitel?P87Sen=#6w!akz9PiE*tRYR5kS)zeb`$UgT^4sko*w+%B;9A z;sGv(Pw^jBFN44=GHlN6=f&*p5gF$)JXvoY?No^%GNj9(Zu3e&=+*SK%ix`wi@Ry2 zF?_5G1kEs5v(n~}t;uJI5NK?o-#bIG;QT@%^a{dOo4a3t^IAsc!D?)xW6pn0d5Mz5 zVp`{xc|9fURwNeVIT3K;th!%-3$Qt{X0bkUS;wGKi%%HZeok$H?;TsCy8t;V_pG^4fx0C-F{DakX>OM1q zyur>cU$XolJp_ZX#Cn<2lgf){LnQa>sfzj(?cZ!veY1E z9_uuayQ*}_2nqi}-XWH@&3UY;B{jw;ie#W#UuEep$Pmdu{P@Z`^>zsqY{Iu-J%yVD z!zeaYK%iQR+)0VPUxG&)!q7peh!~&;*0q1FyE7YoOX@KkN;+jI=Cj5c_=ZGG!> z6WT{scc*{R6T_M=_ep03Js`*fqsur} z39fen8c#grE|AUE+5b5{tZ6f3f0B!hI~Z`LnTyKo*hEjFV$hhK?~C?bgcYSDZA-*{ zjc9?Qa;$?TMYiAhgND4_0NOX5%mf)3ySh7atAcTEt6*;&reD#dg% zo**AJ311b8h^c>|6oWAhoi54*$$8vO*lIHSV!@Gxf;izw9xAGvWmRejW1aXQ1sE~z zKZSZR)LC6DvPFXyFg8uAmD$ZWCT34y(`+ozJx$_yjWuPQ;PYT7JZ^4M$O+p%hI6Hw zLiARpd$}NklC(jCXrl(3)eTu~3%fRq47bu#@`P`z&`p19HtuBX*kQUsEyTa^ZOH_N zY@t~8g<`-)$i8_CJtElG4N7jxUKo{x z_8*tRv#4c+A00r?g5Dgiks6EXo1qNNZM8haoIzDfFFZX9B`kLL6o?=Ro^wu>y5=-- zaQX-rp`3qGw_e3>%=|ekH?dYB+R$_ln7{gmNHeE1Wy@Q`P-CK`Pp50Dg5}=;_Gv{v zE+JI*_KgPB$*iE?p0#jgO^-;e!VDw4XvQnT7>#Aw$Ru}{6`4-AVU29D0<4%Lx*U(R zy+eAt>>9X4gH5fmi!`+*nXF^<05(ikalvnCDN=ume+kM}j!j|%2$^CH`uS3ckg2X zv_^h+m^0&B_lD)SBSzaX*>|duZ?OK>zrFbJ6Ae4CkHJ@DvV&0RlXOk6L2h#91<&eY zFtL9N_5Loj*41Xv(QK}ubU1(LU|kUhZ5BpKahK;;1Vm~EcPe)+@Lp4jv0xRKqno;1 znL;%;g1H#}F$w9Ux@eY9&n7kM%rHJfL+#d3fz@Vj6@A`X4@tQRD%2YUjOj8bcW zuqGJCk>GX?pi>Uw?v=tJ?Fc^MW%5hGXM=xPlihq0NPV44PxMJ(G-7eD#FvB};#nt1 zKrn8E0!}{G8!>aNwuo$B6E7wq``c9Dl0<JJ zx3Uq|Kt3-yNohV4k@jxGg^SUdFm#S)+>thE`CEV3&>76{48x9aw*BnM zbtO$j$dZ6U(kDSE9;Y(gt>39}mQPpDefHE08Apo}NG@Hu7@9nINzivySYX5uNy}X_ zdKLg~V+N6g+>)T*RWZ+jGx`U%JoyE|6{)Bb>#^8Dg^MWSy>gibXiv>#xqpB4(o7fc z9>SpH9>a_{=Llc)?9?-a!`;-;YLuSEIY}6qm9ho6+L90;K&|M&X+--cp=yDE3fHwT zBxIvSQ+aCkA_-sP5VwO7zyB>PY6bDfF+QBx1SatEuX>36SYCwkU;dEi^ybS7cw_l# zynJ<9@2i?-IoDo3DK~KIy1##T)SE6DrUTqI9cvqcHM#c6pOtUZo9+%@i&113gUtyj zSP>VzD+)FbA&s{{Y$C>TxW2q1u`w|n?12xteJc25H|-VBV=;|ThiGJf8k`e8JpG>W zJ7JFYz%PRXI5oerd~ZZbFDHQ%iugcpbO%-lA7If}57ht_I9Wy+7Uq9FVU27Ypmihv zTw}C;F)9mDPa~2%C&OH5HHYdE`o*9iY^S+aE^_hme%JcQ@~*efjF)e%>Ifa=fZ{{C z&mu6$!SEqvWn8im`H-bppYCHhTwY#8i~Sgu$1>p~Criz+fRtOQ#qn}t0@+!PB3J^@ z(MD(?W&aZsLOmf@{hxpE`xbs+<{D={@?_C;MT`eZD|AR{jC8+S*KJ|GUJ?&$iy8(C za)?E(;;WGj%r~bRB*(~e2jGOz=w3;EZ5#`4 zFqEyNHQRX_5}&rvF;nMO$NVz{3N6KueGfOD+Ivko%@qYW30L$EPEB3ELQLFX2PgWbt zF^cr);De}G8u@>}P8u5<_9@H2gV-yVDL5brU$jvFYO1v|Z7lTZGMz?(Sf)v*1WJXy z*L%xqxcIxZ4a=__FbmAE?fMJPhQrtK`es_=X(X2P*qrwBXC&bbx zU`bt#y^sjy`Z7fo`1&A@SQszsyQ#|b;KDG@A?>ysf_0+QPGK*}RXim(@?A)OJ;;s2 zy*1)K3%SnnfAIN@Y}tqU2pDD$O{M^qW*4aIt~K8PU&K68Z-!)V7lbHY0LdJZK@*Pv zsZ=x;3y6Pug7O5%sH zu-%70djQm_Ao~4EAPN}uymay^>O6?vLyju;@*;nGtCGnzT56`wxTs_?Pf2C{=R3I1 zcxD#?0B-@BhUXUpyu&PQCGD%mMx7tnxbZ?s5JOB(=b#p8QJL85sUHq@nJhi&h-;+P zc0jo~in?V>6RxBPc8+c_NUsdX4NZqzl{p`XJ-R}AY60)310)rHh?`KEwR?hMJoHz? z+eUw3oL$YFO(|3vINk`J?ei;Is=~<*%Ax?;uWL5wI*xqYmAp!)&)P!&NZ(=D z$zuzLUPHaMMNW?Bkq3fbB^ zcdc!F=3>yr$o$)r$>Dj~0SWEW?#O3e@}mnQRvg_@lx?EQ0!BAJ=t5 zgYlz||0JWPKsAgQDUVhoIooM9>~PhHEUsnZAWU|@vRS7T!HWFs+G5)-OTzKwq(s9x?8R7@jos#MbO0O9J7-V6^3c=?O1>r+yW6j&RE|kc z;^4vKEfSJZ|9_(POSFE*AhpdaY`e$-O3YG0&>?Op_a_Fkg)}p{lOGO-(lCE3hmiQJ zC$;}X>ZwCE&EOil!yt_Dc&CZhpJzQ2v|}HaJdH+W=d4|=F5d*Wm4Hc-ZVKR8P88)` za5}R|NcN}_mcId-zova&aJM} z;<>h-g2RfvM*~F57kRGRBwQ2ubSu}ShDU}YR;lF2<2cMT&aVtt5CRE!nb1sAy7xut z11m~?iTo8Hh8l2D=@j&crP6B!RZ9}NgL9PAgw164F_Yqn>`trQz2Jv2`C+d8f~Nn z&QXsyY{OZOpK#s^pJ4`2ZVHS#6_CAj-VpjwPMg5iSiBNtDVg`2214tM z+;rES1cRL-&Ypi!4twFtrJ~uiNkMN}R6cSDgb1z=-ug>i*9^pun~}XkrI$X8SMre& zq2D%v+b~Xh+hE9up{Ax+RBTO2SIMeu;4#E|e-ll;gH?&ekYKMJKiV*V;qd9c7#MHp zI+9Plfy3Rkx~tlth2F9F4=Gvyi|-m}bIk1$Kg3n*;E#Vu3yLNT<-|*{lu?_B5G314 z?pG;g+Wngs`QTTEY9&6dMUN%mzhfC%DbzJEs}%z?=rTB!ZP%T${)E*U*X3hbpTH^Pk$57b^3Y_5ZQC?afI4?>S2$0GI1#?lQl28-F>jH(O zCy%7%(SUz459AKqe^xm|VMp0L*+-!c9x|e2Xo^V{Rd$V|+~iG#0EDKHzVR;pC7_y~ zgk@l2upMcJd>cB+8w+qo^vL;$c@+qi69<3EN85Q7U7}dAmI?wc&7l?r$AQQ|NV3Ep z>vM}+$x=y?4Iy>rV7PHf0_s=$k39l-RvT5Jf+T;x2j(6>HU#*i7;mj~+WK0LH>)}y zeYCYj86P1!Z*$_(z##$fuXJ#WPfpd<4g745tZP6d$Ll;>#v-R6En|YJFkVj7Um@W? zjTz@e{u4N4qC~)nIEp}HC}AL^k&703bk5~O$Ng>XC&w^vhOgKywJ_{`ut82FCfa8v z5^#Sajz)$?l^6(kQ)%ch^kK(csHiEjwL+O+JA9{LfZc`4QI!tRtr5TDp^Egj?%!PK z)W<`16n}{8h}e2|8(2h!3pIVau?ugyG&$_#E-mbPTlH}xrNKmza|r8KC>egu=0a_E zlE*Ia9sphFs`J~QvY#wxh2{#IQ7{+!F=~IPtk80@&d6M-NsbEo;4piIqWoS=+iw(U zpbSq&vKdHB4EA_dL9=>C5TRJ+arH6g7;`Rg-PTxlxM?bN-sZ7;1>4%;;6dDT397kg zO7O!VLRN+0&13wgKQ6+04T!dPINl>V6^OIMuQRLH6k>4@%2-!kl7|Q5G^_;>5=DPW zZxtGfh=UU*ih4SG&+(S~XQE)V4GIbr{?~h$3uEac^b{VMeX+C~3OEx5)m>%wXApYz zE^iWr92-1S>Ph%aqF{H)L5aZ`Fu%=Exc5#I#h{!%z@-0?FXf zg(%%^hQl27Xhn|3i!kRzA#(6&-e~__Q#2v|xlH`>H~G-;i77t);oiJ+g&pR*JP<>&28d z>Le6qzQwMknMKPLge)|_T5(mh))akNGH?xMw@^=C^U?BNGa7 zKkNc)zF|~a3;IZL-sA{zrUGF{EK_RYR*YTn1lc}s-}8}_Z(U>ObONmo#Hl9k)z}4w z0ZR%v?UYQWeSm z@+M=Pj|2>8^HEsRgKGnDLUg>aSp-k_xBuS~k5!BS{187XE#YDd^>EUcU8}(bRfsNa zLEXpqT6)E`%D7*ADH4B59`@wTOIz17hr=>196Y}b(x2xHnZ~?@dir)yNQ1ewh3zZe8OX=rq`l| z2CxVEKTV@)NO>j}syQeLThqvktzf0msksZAMt8^+H)Z3JUR70@LDc{@vfPc|FwIlb zb-9_gAzbmA^A_p)wf$&-&7^7W51?*k09z%4JyNGQ2C&aH*kBCcaR8g#!8R*@jsP3Q zckoq0%f)>AlDL1Y?CVoCOV10#gFWv?_0KZ^*k8SZi#{*?gz6>dzfr*M5hl_Pj&z`l zEd$tt9_+})3_hS8z(znJxGYT|4-!2VyzOJ*%cdt z8QO|RFG(}*)}U%$g>&NyH)6numE4K`gNhMiE9e!gfof25=Oz}nel4;*H>qln;k!k` z$KX@1!<~Pj@>_r;$$_PoOHeHb<=6fml>+r$;`GtnIl6Jx-6umhJuL zK$9NY%Jz&=7lMKLdG5g%1#xc&EkiMy$6510(A)6v+}kVH&6BUb~bI>GlR;J z!YRz2B*gY~JYBAiHMKoz85CVvPcV|_0wRf9kIQ49M3x`wwG$&YYd?~^rS>m~yfWMc_?|2WkpnHfG?=!uKoN<~J%6u(%-zU!1Wy7Nr2M({E22b$a znJdZ4t_cvO3Pf-Y1>TiX$j0og0|?W#A;xu~lXpuSbt(}COX`G>FlWo2sl_iKhD~O3 z^Ck^+8ifPFWjKnGdF%r$Ls|(nHfC#C50QV&$5{~%T9C3;^~1cuyaDS6j4?`1*yoxU1&n&>>x9}CkzugDS|{g!vlj3v%Sq1fCufw7WECK} zoW)W(wQI&yTLdgm&c|(7!4~nX>@`Zt(hMeX*$u4M_|OYiJ8vDvdYL_qiapiRQLlH9 zH0j2gJgT%p)mo(Le~sy@gnCu)ZMT2+;i_Ax$?bK_dyI8$N*BGOOVc%+K+3!n{bhxd zKidoPCgDATBDgC`PlEEchx30fJ$=2mxS&YD?KRMQi~%{#->PGzZ4WtL1-v)8y>9XZ zN9q-3gf(gm=5YQgbKdp>lK>;s3mARfXk9Tq2jJqI1UhB_9vGF&X~t2{3sHaKi>{wm z5ZT$^DHFQ>l9c(bc>~(^HJAQqeC=~k=nT}GXRHhzev%Uko%8Hz&H*~t=uaD|w~h#p z(J{YOR7R8{UgutNut8YsDeVg-)P4=IGmslw4Im?|ezuu(=VfJ4)Sj4*WEd}e=Ws*2{ui7|Kx zGDIdP1Oy3ihPLRbefdM5T8(1`eiH)im85$hM7ePQZqB!8j49ty~nkgON0R(`k62KW55Mzf- z6cnJr7*%qx5kvtn0D>rPh+~gm7kH za0p_j>QkSpsmg!BsTq)tDi|CenjZm3qKD1L#wVs~rwYdrEV|%Sfoi6rD$0nm^8r=W z4yZ@b)D0h16T%TwG&3aw+L5UW>8Q%7`q+@Fn!$mw@tKhU$;8yi#N@c~shZ)Tqe`X< zretD1G*vWZQ#h(@s>Y{qZmMQ->QhA{CI+XfbgD*`j;eo>0nOZ0eLf{q1>$j2b{3ia zqxMXhatjJ^c~nyZi7LNEmn^0*p#nvfBUO%oLQGUS0t!hnr6+kxv{jCPLR_Nl$hOLn zF0|a|zLmFvXil_fvEoj&SV?t~#kZUjD_YX5JQgcSps@1AN)TdLX~GH?UGzkXMMTlY zvgHi*u55p?;^f}ki4`lVPOx0D;!g0axE926B}vp{CHnG3lqiWTU4$TlN|r7{963_u zNZqKZs=2AMp(&f0PlaYaFf>&#H!+{Gsj``|aYGYR6(dtspAXEZc+jYtiK(iXm;%WZ zD5q{>%BCi!Y;@cpg2RrgPz@YKc9cx0W^`^;eJX$FNmMiS$+5|yqpEhIXs2q&#*ZMN zDx4cTZrI3#bnx(jQ)Q#-22?RSaNMvFgF}*>%Gs$RJ2-S`)KuL7(xa+!+~8583g?Co zAXT9fQlA@z69oZPOvuKLAUATVWPa$V85x-JQRK%?RZdL7fN0dv5v0Zs8&x)TfNtoh zvI&1hp&muUqX&?kf~goAJ5@M4I8``Q#ejVLuqhfEHGb>>(F{RCqpBuH!PHIF&5j&2 z0wBN@Q$#mJV4+h0fTMJh6mbO^OLl~aAkoufg-t~f;|eX9s2WC&=+fl~BQiAc;XEVs3WW4UHbK$l^LOIn~1#K@>^C zYJS+k6J2EBDpWQxC4lVT1YSiXh{)>WdT|>h!8^zB5D*6B^E#c9cb|2 zfDS;FUm`^cBp}d*ktbhpA>n`=a-M&LTAsbaQL#&PHGJ%``3_!<*OOd05ct8SrsH##D zXn_L|oC1BorC0!y3c=VIQiLC$irG;ki!ka*jvi1{kU%+~DPDq9)#wbMb#^#F2prW@ zrACdiA+iD^F)lz-PM`os2_b*u05dbCL&Jv=9Wqb^j|On4W&w_v8yVnQTJ9~}q+ zBV`Mk8eFjau)!e%NrYr}obB7_JF5W#<66;3z{38kOV%QsAhPf`S7?IU*-VjnEb_fWXicjvjv!&`~zN5F-L+1PN&X zNAXy}5GNnFQFj6zA2x343Kl(PW>5eF7eL?&MI=Fj9kp8IR818xg4pD!T2ch22@dp7 z1;z*YAyXk5Ri6(HjwL!wp$JH)@T38z_;CdaBA_sV5=X2^Spth9I6WZ2Ll;G)GUAIO zjQ}HjECD455ek1WBIJxFfZ(D6MruY1FnZKffetW46Dcy#Pdbo;$rdKKfpbG82_Ccz zDKjA?Jk)>+AUO%ik0c84gOM?Y@BkJ9xbkBG2v7l>k$PwV7Ec1u1(F;$aDbtMoSIL4 zU|>E4lf#Jzaz=>+k`Mv`W8A158+by8Mh6mJtcM(morr%j1_XRmeRhaYfCr5mB}JI< zBFT>k9Pz^z4&dO?fh10-7{HDlrWoM?j45c~fRchIjNA=shA2RX9kh^v6SIQ=E^M~I zfCsXmDH8z*65s@ps$!x97H)uIND&1%;{YMxQBxSe3@=*>N(RR0!U07zdBO|=K)?zm zc3g`RFu;F{95uxmC71vgFf6 zjE~j|!524s`K@4JsB` zzyu7SM2|K?i7u#cg-ih2CRH_%;S2O z+0hXN1y1G@sxibyPSs2fi2zRUn5mkPfq|(ULX;q>+7YtDhYnETu;XLLjVd8Kc+{w( zp|gX;22D)a=xCCKk}6OWAvQK_s+zPBA60)lb}YdunIb}RRF0|}I!?L}DI7&=&Qgp2Kru5i zRh4+uu&EDCeQM{X3a6%gRNWK|P2J4YjZIBWPRxy%oSGaJQ=d=GO%W%aAo8jD?AU+I zR8`H44izG(;zm{F+~`p?GgU-xaH?u1<|9L6$EFIVWGW{nr>bCLKJ~eQv3a6nr#?ea zP(@Y6=#-332&RfgW~U0KW`x|#luUtYa%w(Rb;ILhb5m6?Iz39Js)i5?&>{yH;DHQ6 zU`C3ms>%_hs&2qk+2qJn6^xBdOoe}F3T6hTsz5p*nZl`2RWnspI|WlPWg`ixsUB4^ zI74J^U@9iZr*?c44vkDs*_2Fus$ycQVCqu^+L5W8+EF+k9TihFRWdg=pQ_JH)qrjk z%}o_d3=W-=k)f%&3Du`SH*TtAKvf?eI;v`hM^(w>uv0WgnBbsORWLZJs&ap->JzGh ziJ^gs`B9ZqQ!zC-1yfZus%X?q6^@vSv8fzYRUevyDH?U73ZzpdQ&m$1^8wA|C=d;f z0u_z=RLN9M-M~~84GauSRl!u@s2Whs)QzGknwU?>M&?r=8#XaBGxhnv*r+L+9rXbf zjgBgqP*r_m>Qhx!F||{ms+fN&nNNKx2PafAI8@b5(ZJM)rffik!=|cg=B93xPE6sH z&Q4WTO@WG_0t%^LMmkveVkL+w7HOnzkzsMsGDcNI$&qbzPN=AI1QbewN<@a0FNV;9 zC5te$1Th4a=prRasvH4@x@2*M79e!c(vyXhDo47A5}g-dR5=0)X^DT*0~Ie>1Yuuj z38PC9U38H}56>1}tRS(a$Ci1@UV=hgB6oiLZvX$}-I48c{<>Sb!b_A$8P`;EG4G_H z5?z%eR^>>QBWzHBLQ+tPlq88B6pHd?3@uMQiI9vhxcK74lZZi~CeavLvUDjz3l}S2 zNO=+&DAXk4B1;!2v}k|%Lduiq#?bNv7@&|AF{nfa3RO7*3hnUaizrnrQgT%y9ikwL zfMN;~RGxhKB8m`EA_IlGOo^0SlmryIG9|LeHnM0JBgc!rBa03c%F;!MDo1=UfR`mu zmaw9UA)c6*EMBTWEm5`*01pvSv=2<4B(Xj)agu};OstSXic^2Wc)BRUha^yZ=;8=Z zlRLr-AHFnUPl#9_m`stZ7~+x_ZzQ2aK?MkGLWC0C9MXD8NesynM6&Q=1r;EWt5_eH zER!LOu=Y{~Ndj>M2?0n!f{2qSdIukrERhn$msKskV99b;zC5ucP;Q7bE52Z%^2LjI z4-iU7VJvvID6xM+3v=1xh!;o*;7VrM;>uaE#S^1q3o2VYF(*xIp;^+(l_$mp7V$oy z6<40vQE}yo6{*sLL<=N5Sa}kJlPLr+1pq~ODB=SXCQs}ZP9X6lsaWEPErDW*C)Q-6 zEV(C2Eb+vrpcnNkJ!J7@iy)RrS>lOtp-8e=6(~#G7H@wfvvq)Ciw!YkNtBF|g_U%% zCa0vEAi-pfG?8S;3lRV(Lz3)p#F8OBT(m$k#0oD-1R&uO$OJ}lLPZE9J`CAnSLl$W z$$7D2BnSkepFrY?5hVbKl0%C8fKjBVas`VhO_;nFP>e8XCCEid7A7}Dh$51Bazx4# zEDnkmI&6P2A(D7v2`ErJnS#Yp(K5vfAebOI0t$6ug2aiqB}TTGa$qDTdZ2jO!lMI} zAzWNhC_Fq|An{}hmDB@;hbc=Kk%Sf{%n1@+sz43fwx{=;xxde*@29;hMbyqmphq8iR_ta z_{M23()?ZbWE#1qp?}-{UVkzLg|I}QXvk*mi}v}OsK0LRXsCzRyS~5MmQJHQ$2?BM zL-n+GKf_1Bw?zKbsIPzOnEDv=EnO{H;z6+l6p{i8@qe`UW%7HPe&UGDcscD8(NbTu z$hK(P*!GWRpRbwPctIg7mKJS4Q9mj3+MadN|I;;R+p|rIhn>9Fwwag|K_M*IY}@bF zxA>lWZM?76w$_^xqv!Otf6qofZp&p`y~Gk-zWXu%+Fo8tj278Gw=wxer;29Fwyd8J zqrLOXwtvrLOU{MQQ=e+v>Uu(aP-sh!9p1lvu3jQC+xmTCY)m_3TeD7jc#5s|xqgZD zkuljmn?30i++O9iMZJ^=3UP@#|1I4<-!|Pvx@`E`wwIO;!C2Dste2;6te*Z`?LYHP zxf63LzpdH%V&aRMJr7mi`Z{qt-=n^HW7_k@#(%R*-{gzm+IO7N{ZQM^?*5Wp_wt?H zekV11)i>+IyJi3U#bZ-_^S!j(YwDh?yLxm|q{O8*4sl_F^ZC zEPrZ7{LXGee(MB#l9$PZB9P8HEXQ$ldmFey@Hgr@cf?*XQO=%^|tQK(Ahh!;Eo2Tv%1 z6*+tXLJ^#hf*m}J(1t85;Q~)S@C7F@!3qz^k);Mtc!CaiY6lQlfP^M9M~(mkAR?f^ z5+5Fb123R}32cBBLxxbGiV`V!!G8`$G@ytdW>ADAeBlcZGAICzit+&}gj7|cKm}0r z4#p5tr3#aggd?)h0s)XLpb17+5CkZQIDrO;C{e`@SbzXV4G$mya0McUBpGO+MHyb; zUa;Uwk}qWW!3JQ^0J4NAbaX+3E;_IR8#z?bL`o10@G@usk0l3?!I7G&3V#8?i6lEr z=mJFp1`y*6GC+xd4R+8-zzLF^zy&^P1s8at0A!3&0v~9RQ#w$z-~$gCOn?eIXaNg; zKmr3|c2ZCRBB&6BhLk3xndk>qz(EUY3P0rm4D0}dG!$VAYJfshQ}vPZ1SD)!fdebT zkirOP;06{nv4IHyQKAG1P=6F`0VDuVU;q|YFhL8@z=bA0J9f0B0EZx0kR=H-NPq{r zIAKar5knU#%wVL52w0F4!zlPc8N4VgP(Et}1qcB_4klm)4iu@0fvKr2LJ;E%7dQZj z0Gd#O3#ecTBwp}>E*dx^3KTJT;ENPM;7AchXg~#gP)1A@5F2+z<~u5T!^3w z99&?_2}tn7iW|aEz#3TKgB2B6z!+I@lEerY2;+n|SM?Ix+dG}!TDJf3>03HIZ?;aKmxh_9$$ptU&)e2;eN%bY zE>juv6IIcZH$QW8d4E%H^rxua-R{h%+}6K_zvlmEnSXLGVz<2Ce8t?P8zo~~e&gP! z+l%_nIv?9sFXcw6Yt4-AiOCie;*!b!#>jcA2{(j9q>&g={u?49KXPX>P$)_hTRARE z+f5In zOcr4#i}29=uG=5+ELn6Bo8Fn}Vj}15cBboJH*>PX)A#1p#7j_U2gfN>-m4q|g}5w7 zwpOm-6}58ZwRB%`!roS#XxZZG1k1SJuX)LxZNO#s=r6J~uE`RW?Z$360M!Inp#WL~}<~4qHS?OhrC4u_+iF z+K0?k6%Hs$AcPWxF+~o7aDyLUQQ`#;d{D*`A5xHoAOyh*C8G&CsG^4wFOUER7*O$} zc5c3y@k0|pAW12n%Rn?Xu`WkL^MgJ00j!Hfo9sA)p`v zXru!V@KMGIaB_n5&;%UCfHPD<16b4t2MQlF;lTr12r+_0YNtR@y2L;NM?T;H9$##b zbaIN=Aj*;PfFZ6(wWCQHRcIbv03ixpfU0u%r~(E?IDrpNOh5uCVYGmXCyJ1TH-CKK zr*HulOwa=q10%?Q4LaCK!nxo<617t`gF*O^qntD;8bxG!=pYA{sHq%Ibb#Er$w>ec zm?V+G6+^^;3>+I78aQIAZeVVFDhH=-a#T*${J5zdRW=oKIylUr3O%R*R*fo}nJSx4 zRZNW!P*s8IrY7f8GgUb@bg-)W<&8K8$V03Qu=yAgare=mzRgfwn zJ2-}b3PvUe4n=m9Oiqp-H*U!IqKPOmC8diVD45uUK8qItU?5MX=yHYnsLG)Tgee9B zr;gkX5L0lWMG;4KY-*=+ihqU{pQ>R64I)x#Ap;2`Gcz_uuE@fR6!k+0FUFwqL^B47}7REd%ILQmBZAAR)#VDLAUi zM&&3YG9Xex$k@r@gcl7=`B5bUQ#7HNDF_gjexqi0xBE}EPIv0bH-B1uM85xY^>pg0 zY4+B3Y=#MKlW&CEhGzfCrwMs`*w4&Wd9FF3a;KU;w(Xx;_nE2YVLs}ACbxU13!&G+X3<=V$*s&a|Frrfq)f$LeO8nDEui{56p*i6B9FDzVE9x?^$mcmAztzYg|OuDrgc2C zOHaM;sb-&>uc_>x&7Tzi%-%Bfa;NTpW-p`JX`kkKI+|%ecW3@5uHAq8XZxkpsvFE<;f7)Wg#WPF(#LE6}-Hm2>mwF@3?6d#eR@Pl-H2cNWyV{;gMf{;#UBzL{lO@{JBH(KFe-u9<0P@_poe|NO*c$7$x>$rmln&@cUNr`acC!96qE zOU6;IXK(+fB0rk3YBGP0j&J$yKUpo=-M=Vy=YO_o zquIWuWBhE#WY?!@#@FdMVm({#|71?>PjoZm{B#^$+Nx_aADTH{Le|z(-DI3*c8>`; zQoCpTPfkvjerCIxkfYb`%ll8uPIlI2_PzZl89kZinc;tPLSCM|lxzv3MALRd z!)r`;k)>WI>t4Qejmge>-?ER>nXx^lao?-0U21B|y|rZPymrY>nYq^y4U>=kH_t8k zFX={@n9TbvQ#I-8UZ!R{>Ze_LyJGIDUFv<(<=tc#>7sG-U20z1z5ZV3WY>1tnQ1rT zTy1pE&Nkh&pX`64yS(ePd6~YKZt>1}3={4~cj%wKu9nt+pF272($4k%SQ9zvM%#(K z?Y!u|&FL=szsJ|RWYnZ<@41dichg-uUeZN0{8n#Wc1zq(xsKX>`j*|zhuCPB=bLgt zAuMT^%b9Xf)7|!4+J3@Sw`622zT5wAshc=G{k?mgcsfJ=k8r1U&4*jZPRlT z_FPKeYqxa2w5Mpu|E}BqmaUd>b(^o>Rrw63*di-cYnR~QL6o|KI>mnv{&3kOdtK`v#ljn%k+^l z@9y7o8~<@@zdL%Sk8)EgDAZ%E>7&)>Z%(Q2+MZCOzvg7zcmK@fk>>N~C)B7Pbuazh zpD}sle64QzoM$}+b%y=nPP2YdL&-3~`pDl4)@7D6&SuOb{-g)PK z>P&rR*OVIdI+{Pf``f3E+FE-VpAR{uMt{$T`ky+=XY5XCyYJ2KuHEi$`^@<%HA+pi z*T!eFGtR%r@KSUQMbI=h-`Er;hZVS<{nh^s1Yl|L$#`I@;&kORI~R z+Wmj-x}Vxk@wDIAE_u{!&1uygFOx_7n(3#{{GJvW|4!dseUnGNsCRwO?v_|1-E8+= zPaa`DYt)`7Whz`utY2sbA3$FCR5^M)}>@eun0~edhe@#;MaB3!f!V z%+wcUtNL>Os$uf9T>Z`6OG9p4#@63o-E}`dQ%t>hkBN+F_yZ!D`h}IvVb;uclALOrN)iZQ6hQi`aau zx@nl2Y5iSsku?p|UUKqWyR_%d`HPsz)6ya)_qMeEmb|(3^4IlKXTLd%HnIx4ddG&B>iRdERwe9{;wdqUrDc zr*2(4-~CPQ)Ol#=&$y}cIr-4=o|8YO&Zt=(AJY(>J5y(Kaz{^`_j;O!y1dJm>~4Jg zYu@^XXz1s@*7uo)`vQeIjbrfEuar5MO~VbKkQ60^ICA935l~3W6;`?sg9|LYL|VS!;)@q8UtAGsxxz{p zTE19`w1i>B%N3x|7g~CH-Q)nSzPCr@W zHJ-6Md+(=BE>Y$go2NyM@H?5`T%U*UlkqbxMwz$=6ykr$!=##fW{LNxdTV>$+KkD4 z@&7MZmDh1M`m+#XPfrxX5WV`IW^#>B;I%yiFuzsPu=5S7ok z+0&tN@qXLSbf`U`5D#WY-0th1r|0Q<(r>q6r(PQOF#e_A1BH0fm*4+%Pt)VRX4=*0 z^nCU4BF}$s<<`sQq}%Opox9h~mr^xS&Hql0*8>XiMEh;ct@`OnJGxcBWk$YD+p}ps zHO=!H*D|dqDAdEoyZWBg6BOd{J>G5IzDv6q_3fU%;aYmvX#GtQ(>J5MZOd)k&g7e| z?9Ydm+Ks(0)t^0aYozI`t=j_%@u+D^T;@01J2ij3l-ZBCpb$@Y`y#8lrgqhK-Av5R zZ{AMq+5-yl=)JS6{pxAzQ)D;xw5OmD&$g+n+8(B~T)kyZXURp)*)mtvJ(*<>D8#dg z8TGxH?=lfD@i;#%#J_p%xQc29`V%N5ftLVPH$9KHfBwX{QLYp z;bHWum|P-7JmiU*pKUK8Mv1Jed%Ecfd;0qD+I-VaQ}&?mKKeTTrt<@Zcy6s5-_vV^ zn)jB9nNepO?pbn;*f|vyRiD#7Zu+*mX(oTo@76o~cfX{V5#FLQ{$anR)*euZ=P|va zKDP5RpKAJ^wB>U}P>9D@&(YB_>0xsszqhJ+%0o@IPPJU#l!p4)j9=W-X-G_lh^?zQ#d`7$T( z@n7vsY+F!>2d^2?*f3@5`623dLfq)vwmtLhEuA$#ns!@4Mo;Wyh<=`K{nwl9HtMr( z{T`m^o!9sKl`*A8tC^|(-ILhfkB)zc{>;4Tda{3AlOcjaJl^-5tjcGM+#4OPxn-Yv znR!zIM`L><=m{vD>SLNveg?OTC!^}gh5;A)a*O|L412{j|-I=l-VYs$=@b=-V+dZ4dKa?tRL3*5ppf9Py*SvRQxQCvOCW ztWb&mlSPi4?2mTG)|;1!x0jx}wyNCs=BRDXdT)N;-szhd)03XPH}89NY{>rZcvv#s zdNPlC`&@m|IGOwB{$Vl)g?e~A-}p8Cyv-MV4KJZ1F7tbHC$F!eCiFb_y-1%qd)1VU z`4hUEI=io7Cv-H&_U+Sz9x;EWrgD3qu19HU=d9a|itM|~=^Pa5(f9SVbgtIvd-U@! z`nrn7C$lpQ&uujzaHXEM`kPTA2ZU$<@gsPBJFFR#ZjaXV>) zLOhGsnyA2NIA zb7!Y*?sTc!o{o)w{nK%q8(UgV#CN`gzt8jMmQERU?evp!BjTo}?Jvnd6L$o&Kl!@KgDO2;Fr(Eu~zO+6}oyuta zYR|@;_*_vppZ&D|FexVHWVFPYk7(Vzozzone^O>P)x^B}Y}lsHyq21yOnh&iFzyJl(i{ot~SG)0#c6aqjg#YkCHSu&g!`$TDd6?#FY{-p?FJkXc&DM*Vn9(^kKYylvV(x$3Ol-c1Ich%Zyu{YTw&%o8 z%dLBfIW6}kzHd*<9lfc3Vw&ULv$-ebTzmfKq+DVF?#!SNmcG}7 zZqMqNnj=?K!_!kk&FAY)&5?RLGGao`^VAFqVd;xno!=}uH|C=A8Ybrm7p>JSAs27n z=d?`DpSPQgqvmDfd_yzVT-#2nxb4fEbTQL$gm-_Y&HibJNqaiaY?J5weE(C~_!`ad zlD49m?`ke5Pu!%oZTp=1pT?ZDJ-Pj-b^qa7nz>(^HJ@g_e}Q&v&%<&s9&imS)?RklERP8ErS6W~bxSMKeZC$C>W$(y=0%?H{T> zDx-hz;kAG6WBSeSZU1b|bl+y?ocW*r>1f8A={Iux&vP|%zB^|-v$cyj8bG90Yef102pW(5Qzn&(XMB-2NZw_o?ai`(Wj*w!rJx0X=9p!xoGi=k03j(92ktk zA4c_aIAc*kucLIzVBkXPgwP48a06^|Ov*5P1&sl>wxyw{RJM0EXE0Rk2yMuw#{3ho zG6z_y=%fB5i1&62eY6IeEO2yG_Y)lNO-bxFrXp5$s{iIH}aJbPod+W&ecC3Fg zF@%pIo|Ez6c5ln1e}ms5?$vVn%+e9#IW#T=5J8e>z5-#;XiQ*c&d_HfGogR=!Y;he zK8~DBW7r9e<>K7nEtH5-6b`?tw(geHG{WIde=3+vl)`f0eHH3z8W6AwuA6BB-yv1m zV8**c_d#42QHVBBkerC1hceT}kzRki!;}J;{Q>s;Yao_H@q=j5_bum}MSalcwg`)d z<`VN?>C)iAD^zPN(_V? zX6Jw;4|1l0{sHax)1o+xP{Tw9brphbHDk&Atp#nzE|fIcZV0>XRG@m*^ou@Dm;DEE z)S7*k!X?oq@(6oxQD^s5I>LW3m+WAK4tf8N3@3>9QsKb+cG(Fa$$6YB_y@euUyEul zHa>X^xWf>U2q)^#tO#-Y9gV6Tz8&)YH(P@>RbK#%uvB6?{nV3?+r!$dI;7%e~|Vmq(Cc@)v`&BzW%Lcl>Xrjh#Uj{gJ^*SZAsAg`Yq6P<3PlzkIP{K! z{BLM7!!*T_qw4&K=Fe=5g^Z1{X$o1*>e?AwyOwVa;+T*R8fpAT6z~H0Giz0jvt~-0 z>3~%9wiXgPWJcyj;fnn8l7w4iV+uz+N0SNxPjZmB@L4C($QXaJDeb5aI&v3bdok6> z@~#@WN}A9tP>issdI*bJ42)sTZZSX$8r9Y>Dm`8F)lx?FjXM=8Gmr2fXqAVDWB#G~ zfTF17_+mfo@XJ~l!po1&!$IE9>md(5TOuJ@t0bmL@PFtldcMVB@B-Xk$6&he%uPrE z2oDX2Wr&#@Z^wU_EZ;>(4!MPOo@!9pgqXZ5EHfXFnyI4ryhR#kHoYgy)FYxd*_DB#ajG}8cC(Y-Vzl0*LG*5$(yE()M-l8wQWMrAad5FSE7 zc!1|a&Z!KpF3JgZlmo?*$rCGpfLrNNI=_@AAo+iL-mtj{6HQSYH1AHDu@}(l%pvXK zyOVB-i$Jm#`;p>7Y^VsN6-8Mfvt|8onGb#oT^er61`Y6Tp5ALpieodp?n7#JNb?$zbluE;Q;#%*Kub zF9LtE#oo#{yZ*10`o6?E>_T!7eoeyCVLZk zM1f|(VFDcG{tUXs{kS4ZDhaJv9ARm2Okt+!Ud zh&Gf|Ln#$(G6V~jFv-LtbyTCN7^%+?PY+BH91vNP97EvSFJfYfp$ieotB*z?^RfZkVoM_{QfO+cGK>j4@O!Jx!iwhMk5E+w}=kT)Z1z|}B;doBdB!O9p{ z#H!(=hfS-Bp}Q|THy?~H3_XANE}aP(&FAdjeEx!8^H<7DrS`i^^GRT!+US3x942Ke zp4$_tkZ-`$1UWl{-Wo;yTwRCnd}0gt9(ASabhjvrloyWe+kC>$Dd?clH*E*;V6Ut9 z`hPl6Ky6K5Nh`MKx&dlLBZNhbI)S)k4V(kBw-7q1rFWsAw9b6D))yk%o4-n#k3YfY zJVukF&{9KMc;AZG%#F6yOlk5Ld7+K`J~axc|v zUq?p6yN{-}?H^j_6`*00)M*na$D=kH1u=~Wu73rM66XDU>APBbkQ;x+!aV20z8+QJ zV7p6qE0B(c>O+sol3k&%SCzKh2^z9ZEmIsV>00Oi|wE*JdAMv_%q)p3Zj6 z9Z}3mzr!*bx%DNfQ5xRG^6yYu5X2c}f>lfeeBnKu?4^@gS<&v|Ys^jc`9gj&35`b!Z+7 zS8}gKGO2>8Pank4R&c5D4@1mv>D^<1mzSO19xYLf_|4o#PC|}p?-BG4^}sFdj&do@ zOj!;nzlaq^$%}t8=Dc&HK3Kzx*bD8>Jqj{OKsb+w0ik8J*Wn&W*&-w;jFfV8g#8dg zQIP?dSFR!A#v!B^FW@MNfQYADcHOd>=~E=cqk1_R-=^I$fr4XJj&E|AOCi|^V;UeV zp^4F)bmi!l1&GGXAX*ZYfvQ?~a&SRKk2v=}e4~iXzC?d7i)L4+ZveXo#U_zyL1D=_ zR0G&tb4MXcV%=-38dQRgvtx5wlN{y5n~r}|ei&UK@W8rp&~^Hs#)5+`og~zsI|CqN zIf@|0M2Yt2lKc%x6rN+^bJd5kuA|yu*>2ckS{<5{j!eUQ8BYy<&48q&n_1n3p@kK` zpnsS4zNLR0y#%a%m3ILyXrF~C7X?g3OR>D8iquHS(Jbz;zpU1~w8}1A&2cNVVnz#k z<&8$sA)_!w8Q46msci9ysTZ3oeh)Bwhd(S%==IFJo05-s)}Y%$59p{FNU5*0y6gWP zJIck61{=`?Wyic%cg4=K71ejQ6EJUopO7@|RYiY!^xClUkxg*6qzWiZf2;@#{vA{5 z5Cwl;e-;CNG0-PuSBPlyaxA(XlGfQkiyccWh4&(k^t$yb8RQiOgj;WeOAp)-ssAVG z7oAAsK>gSn8Nw@N)h+#iQl*JET*Nf{wUXCHh?jB}+Sc~c84(09-{4m`f!Urzwy*}l zi@JZ&;9D|pp1eea!n^MmGw3D($ROh;V`VAWD7ylO=SI0(XDg5(cRFB}<=_eujq{(d{DbZCD~vd)w`y{x$AhMUwSF1S6cB0pHQaXTGH zi8h#Z9U(pj+Q|pTFgDEX>}LQ_nq-)$hnNz<2ILiTKx$|x$aEa>1vel8&P%)v=>s{= z624CvTE!)Wp#E}F$wQICHC{EW7DKKqMZlCqk;;9#0K$M z52{6!8Xp%>h+po>4NY!)5ZIO$g22p_o$~a2Z9(&(ckKW_ zO(#6T73DLU#?j>()wvImdTG4iWI}&0O~!Qdbwt+s7f`BdeC)^p4v(tiI@vzjso_dwv!9pmz6$t;RGkw zRK^vDs|)&5b3PlGAmr3kU0mFN*@G{k=Zr9I zZb76JM5^BSDx;dl9vulqzleTir1og48;x%7qegi@Jl-~V#FxbpS44lMtAUK&GG!v; zgtlaWQ8upXUzKG$yTDK4L~#}GYl^wTfV!o5ufcyr5MTIwVohQRB#}tL0i4JCIG;z0 zA#Lse9!#2r5591_`s>q}3E8nHq*!@U%{v4>M= z;YX(G7_o9igeu|~>RTztA%`T{?5qC+Xu#oAcgF%^=7Dy6gnoYkIA(|@2Z`cqf+GfM z1&>4*8;rnphCx8k+}f)*m@=Yk1Ewn_rKY$=%%+0myWCb-pgJ~`(ua#t_=z-Wx6=PI zUBSJVZvs5k3tZLR_N)`#Tz0JHw0AAyTgc5tp??-1yqH=1o%0jL?Nnd)1RoF}G45*=L<>ajk?y#igWu+k}56iGWMW|#3X1FFvaTQHDGYG327J6obdXrq_8PfqOeMg^ z$w9n|y(3`IWEuL0Q_fb4xEGix{N)hz)ZOw0SOJge;{acaI@JW^VAru_MIOT1`Dp?| zh0=cyg>P*okMm?4yBX1EA7!oJG@Hdrgf{1sa$*$)MjN04>(o>DN~y^QkH4}-i0A7vve=DngH(FxQcFCyw3@KtlTmL31Zc z$FolX6qRsIyht1Ah>gQFq;%(5;U4{vGL0NCKUQCpqyLoNsSw?8|Hu`v%xSXM@KB-@GfWA;{9X~c~m1s)9Kxjv@ij*u$Tt+f~rY(sUG$$0$ma$L)`@@OFo9nkDzC!LE2BBZ) z3j>2^E?tW&+Z*e#Dd1$P5#u(*Z5My(W{B=huWLWFVBEWCt&nE}B;aHckp%N|?pcjN z!-xcxQ;}jFX?$Hl8m`QI3Iv3uVjWnS7bNQ)B!fHgU`dZuid9sIPu|O8UHEgiqP#k@ zhJt18ZMUc6%4i+b@HnhC=Cl}L{z7XIUMQuX{r!Q0ue!Cyn58&wyH#8a*K>bbH;qXA zsM|5(gkFm(OD9LK*$5^`)n~_Z?sgJYi%1}BS1v7k)WS`(3uh@2!HcNOD5FF~#k$zp zh$;#S9f@~WZ!qQ6P(oxsrE*B-B}2RI3I!P`VoXfoHHfR|jh}`AW5B!aS|bKhoxiyj z$S~$GqwH~^Y>fhHxT0Ywgin8s3RDEoQl7TPAt$s82vy*d9Sz<^BYSA*$k!v$gyeJI zb627@HSaSop9C}uM=^ARC<;0tdCmu2&WD1&(myyY^>b7g=d=;@MWcsw578Ae4RjqS z(bX$%H-O&WFgZD$0i(N(75i9Ll$jM;(Fz3A3i%mEhz@_w7ku1PYNmfgSe$;b;1G!9 z0cny;T;`d7p!0(ZISw&0z0T65{sb%S1F7X0(KHuEyu`H9@=OFTs^1XQ6l)<|kEFQ6 zg(Lw`Hw}1%NVr{#4t=mL{~6ZjXTQb z!+)XKyEtm9;z5k+Tr%z>C@iXN^f@!N+L9Hk2S>MxmaO<5N|l_kHJ|1GV&g@RWZ-B-agwSJ)T7CFwqv zZk*rJhhJPCewAxqv*C4KbqjvwxhN!Tk79f0`$>;sO1*CF=Q9eD(ut1r-0z~EsIvUMO9+XW;C*no zx+_-Vn^Q(VRWyGQ+r=iWv`mkj+zO4pSMKo&QJo~0RiODEvryWuMf%DhA(*Wc?MBFH zRZPm`)vX5TLc7~;nLb`Uz1a$B$b+tHK0m@?3j&bh)Jjy*K* z3@^V^p8@WYrDJJLIZ*(j>ZS>yo?j3OG(Z)_dC{OX2e=$C*a4;JVSP{gOW#fOzVGe3 z`k}GW@rCy0P2b!`!ArhoeqoR`wZGVPL!i+iI4XZ${cn+NnO9^0W#|-Xb=pmWFg3l| zIq#EMv9nBR^uqFj*f+|%M|LQ-`1ax%6-!z!3P+f+%bm){mh*sQ_gOBw;j01Nt^PB` zc2A{uZusSkc$t8j5F);vdcO$W6(MHZe=N4a7Y@Hzc)uGT{OUMoW$7Htb*k4Xc?pO@{V zUNtGtJi!Z%H1~*JT0d~G71LXpqN!pb!f|I#CE|RKH%Do!0OI^US$EhBF>> z=Y%7*>F{bV97zVEN8psVqKW0iEMs9UW^JqT35Bd-E$18cjU6@^7-ObPMAt8rupxi+ zt>UJso${dz0#s;;7HEJiZcmxS94$e|2QJ>m z{g7k?u1Y#Q7R$~R0D`lKGoH(9ZUlb@mw-eY%3X=mti+(AlbGBoW=khXHE73))3D4m=GxL41D4a&Y&V zObv!g;x1fib7%WAY=QU;gQjN`$l&NFuhsnK>D#n}MJ!2*B7VxYc_lPNeYJlE{^djE ze@nF~uWDwjjmg|#W*C^uoqpT6-ZZw6Tct!}WS^6mjcGj%$1nH@Ec0!gBK4ltf5d7u zBZ_2xk?Bi#{DxaVBmN`G|Gv2o>-|ZiQtr?LHw6N=s7cZcuC`Ezw~fFZd=)4AI`s#x z+Op!jvbC8aLY`W$OdTE+WYT{`(ZMg&rNc+wB#pj6l40QhVqlFX3a6wg`Nu0yvGUNQ z$%0+*8cpL>(tyt!EphWz>L!o7Ycq@d&u~)~EN!#i?7ZdxFa(8C!*HADbN?)9G-9++ zXws;Re(0S+5OE)}QaNdg%z26=Vs{XUpOaVnKgu;LOmK0za*kGTs0mvQq76#+Gu;EpmsmyLQfC=)MZZ*FvQ zVPkZ2FK}{ibZ=vCY?oh|GA$Y-OfoStEle^pH7Pzm4P|a*Z(?c4Kg$}GnXMa6eWK#Gch+YK0b4Fa%Ev{4GKt!>{mIDoW~K(=U058 z9PDgYRaYN?pg`0S5w^q?916s8Ez;m2kxR(__pbMxd zmrtLR?dxxzY=_IMcOS1`{`Bk5S2zE;{r1JH+wJK;4qsm#%2B&-?brA3u5Uhk z_*)$H?bYG8*gvXnK7G5u;QfEi;h)=E{!f*KD(9WJ?((}gW&7sc;fM1QeY`{-EV0K+ zG?)AUe_=*)X2Kg9mXvJ`UBZvOZ_?&*nzilf&Ebn@pV0qt1b+NJ{&a8K?_1rTZn0B% zi)^k(m$^v~pLUh)`pp3o_>QYXgV%?Pa_mJOit$s2Em8Vi~4M#xReQDc#Wm8a!{P1dECt9GcGu3Gs6p5HznpmS+h`Cs!<5d z@*ybhd~PUo5qYcc)z-?bLH4Z9;E^!Ck&Xg$G2eE4Myk~ zRKNBaQgz4l#7ryLH75S)QAlux^AK1UeiB$Zhpw30QAFw6J|SsE41C!+5sv~3+$|#& zXIdl$f+H0>rs^8kuxWBtN;;9L63(c{Di~{or5;@eS6Pf(1QCDm5W`-TDUBsVJC`)Y z<|&xztzisLM!9SrX&|&uB1u9T@FX(Hyrb48YbDe(ragZ$wC{f>K!$uf+`%W$@>}>WL4) z0bWe}PQZVbk{#{(@bd6%Z+d^w>H0Ai-s^L>pR>>PP&fk7Bjb8R{7#=kiW%xH?9~29 z1QOP>7-dM%l|CQ<%pQ)M>`6fYjxrFMFJhx4X5a>?Hvf(Aq99~ zz@29ca`+XcQ<)M%p%L}#8lxRp-Zg+VEq6q!1@3J=2x}_7+G1I7^43g0fXkQ&NX?UbO3*?v_lDh5{0+~7DgSrnDv8Qf}~fN z8#m2LH_h}eI79d>oP{8m?gHR1)0E;KzEF5R5(@)~b>|USLOTT*jbogp82xG5wunIm zfx3U2xX(Xh;x@F6fIDQa6(G+ka|yM?#LzN|FZoApIJC8_>_Ll?kJ&^ zIv@aTmO#h5?xOCs0m=~(%Hy>q;M635Mi6z?ym~GygoR@q+i1&A@$KtlChz1?UK=Va84(NfM_B9EQm6*HCbc%no&(_ zS(iw9&HAq-SYchY^IU`PLQocjvfj+ItCW%zN9T#J^3yZGh-EF-!b6Iqn|NWN&qjYb zu@vr}0d!i^2gA1TAsZF(uz7~2!?YA%qrI`ztqoS9B!b-&jY$AvgL=3lBA+kvXW67A@(#5%POk2!8Ra4z zJ%xK~rn2|JM~0lfB^`W23i0q_=g>}&?%@7Knsi&Gbjb|KN4~oPlccE{AaAl24R+Dh5 z71R&1j?If0HR!!=wqBsTtkb5x2jE_CKEayWh!z&c{NH#}oGXBUzlhUc#ObpVr^u&1 zBIE95?#IuVxqXC(@R<3t%#DBF(jJLG>zSM?dyf!CS4+dy#r5oHVEkliNxpj7a3VmG zU1K$2f&*HL*=ZIJLnfk-pqS?=Jy+Jjv@AwCz`l^4i5h%7-$#+q@%3B9nh8xzWeuXqrFh zHoP!lJ8aILVM1P_iRF^TU5n?^Qt2P3LqdY#65v$dNQ`$S=j+SwV{_5HJYa9E|(&*s;8>mk{lKLBT>QwsHR2DcG0rW z4nse&N>6${k2PBhq)&g=;0RU9gXZz!GnU|h6Vcr|T&@pGQ1ZdTdWd74DO6@YT-;Y> zB{YHSauK)e@7mhP;r(sK=~klB_}=1$W5 zHH+IWR!Bi3b0;4fcst~sncA|dMEP3Sb#E)r6L`oo!G}1BOd@|(O8e?s+mlIZV_O~b z^khSm?c6EC;tqiKnug9*s`$FYM-MnnbmS_zn__XUQbkl#aZWx0#43uMZ+R+O(&9V&k zhVy4GOjCCAL9u7&Q)ff@0To7i(HIq7)o3t2lCXoy zW))vo2&;ceuT`Vtqx{wWbXyx2qj78i$~5Sw!&5gUmsCtW1rW-vc-s4Rn;vPEy~f z*SXoVn=CQrU^OS6-YRR!%hz*e=Hk7K=9vYfQsOz=YqvJ+RG)vWrWI z?hT4Ub==7&l4S&jKox_bL5sv%Bao?6eDA1U5BON|w-s*|VQ=vg^!)L*aEmj;?{8}a z;jDi%(%EgAVy&<~>zaMzxRwiV+<@nfGQbh@@s=<233xvWH|M)yLeyn0cEf7^p8L3A zBk#G#n|2;U1)=)+{-(oes1BWzC?D4fN>wgj&aQMBzx?i1Pz7{{3V6JesM!%~{obWS z$xcA`+(z34kSHq@M~J_{OF>=C=xO{71ml0fsPpOHI3QXtqqvjU@opJLVpi0gW{8}D zfY0QSQb=X3yLO_@l%2cjja#xT20m=3){{QLi>ra2R_iz7x`}%YJTd>Xh&%eBV{mXxk z{{H7*B?a*}c27mC;wFK+B~b4CVa!0shHf&5g-&hwr__e}oHssWYuAmVp+mudtEehU zg`Sz93Jbyu^syOW7aR(?bX7tS56~Sh7YcW>Jrz-^u=1zDTEh4Klcf~K8!aA6HW({)bF;I477su4D3h{Glz`3s(g zSBck+MX{5^G$L7iWmGg6wPJrt*i)vkkO&Jv54nn?lGODLj<1p$Wkc~y77<|DTdHCx zp_TLwGU`-{I7@Fi9eq{1=BBE@znYw43tkDu%TuVdf}3z@V(SN{(Za0~BeTS~yS8`{ zdvppxNvVPRUzb7}(!RXfMu?y-QgGGH3G0%S>g`<}L^Cw0J=<|V@~(eIQ$%xxyP^_8 zLNiLM>DOB%n8jarm6J_*n!TtdtVIrQ&g|DmnEyiz+MyKC3XdT4&lf<*8zd>xR>9ff z9_G!@;HAdbbEaN9E~VHloB=O38IEW>YRb0Iad3hs1U*jCEg z`Qp1l2hw`uoVNNEaXEiuxtyImN983*_ZdA5U-y{Kf4!2<5DTUDmeMB#Nc=Y*6B;Gm zl)}~RQ&i|48LgoTfKb{(;C{tTKG@r-8t7 zM?>R!=Y2sT#c_Xxox|wXoVQ}B6p6(#p7xCMRi89KJXEm+d(DRs)kcu5L{dpF;o0Z7 z@ixc;^Er0q*$!;w+yqMgz>v!6b=^?YP+_7AA&WR>>@&9J)rxwAjolUSRhtR5MIxlK z!?}mou`{fbK?*!I`>!uFd#L?zO}l_i&12t@uu`AV(+Ynow~Wq90IyVCV%`K!5O-Oe z_1)jWDU?34MLtB~>nIJFtaF< zeAa*|g@}JI@zG5dbkG(NmN={w7Vr=c9QK_=ck*;$iyDEEJPpxPJ9~7PQQ`5;RGnjR zW z^Ne^#HcVhEB>E~UCAL-jj+^Em`$n5wM#hSJ9YFJa1W#*IxQu^k;9iEP-gx~M)hH&A zSp3kXTWOTF+!t(<4Kv8hTLI@3si`7m4qZD7CHB5*QL-LK$}brBFhviK%`~MEmEzWb z1qj>h_3EyTHr2m9+o*+mmDX6g)4D1ag=Csz6!w@BqOr}v!_n(#Cg5C~VKXaTChkvnTNmaffn3xsm`=c5e4OzpyMC{-Nq zs_t-kl!J#yvN-jqws@HXEhD9}$P+4}m_6m8{eZ|zp+nv=6-Nq7Nky7)DtZxQVRAxg zCL~}TJ9{-_$`5OxQ&-iZ)hQ@+fkNe>>?qL-{oGmr5Q#*VNg|u?S*mtf>J?DF@PM6F z^11u?5acU7v*eP~du24EK7u-axOi?YUi=sAVwv9sG-cqB&`Z9wU4SlCcO3erm>6IDxQkAsRD`e1 z;zTnymkhLqp|m7EktOp?LLL*0YJlrFfm_T~x3u+mGCaV(*k$i;*!g{aG^IW1MqE$Q zLPbsfq#pphQQXp>!#|mH;_t&7C?xUtfX0_1She+GW#l%TANHL*h`(V}16FEjo5Tio ze`^>lQo+RpX)WA6l#BBZv6N~{;K%Y0bn(l1gA#r zR|t-lSOK;GQuY)VGgNh3Y{p*9~_P1G|h)4L!*(g4VdoVrQgWgCb*?0^N#I+0b zpFU_my<1GDU(utwO#qIbAH%qG{qB{8l0p)0=vdkWF`zexRUB_x5 z<-R--OvNcA@M$Y47+a6*yel4%Utrq1zrq3<@5_@!{!TxEg#!?Mmbze9j=)w!j91C5 zx%5xTKl|H-CO6IuQl#Rn(b_d`AE>9yU^hwjKzAXfV`nnOU6qY)OAOZQ(9}}>*JhJy zLJiePlf%&lc+kp?r%%R&Jy9uN(B)#V{z@>2*bgv(_3+7R1D7dp;)ZoFM#*Nx_z?c1 z!W`i{5H=+xJ^|1@{yCRNdrvgxEn;Ay&Vt?>x2`x{g-I$0WBYMa^#=gz6s*b?0g* zHWxD939?zy_6h}U;>09Hgq`vcA{k8H8VHHu)S9;QA^_eEjls%kB}gponhw(~=i29i z#5Fkb*{}TA=iajMz8dZIk4+#Ul2*lgeuIYp0rSxX_Jpi;Pd!gsYRHUK2!F#qKiWLb z6}qXd_0uh!kX)%u)o^6wUBS5|Ypnf5pO8933Nwg%$%7Rn0de9)4WP!@HJcyrogSYj z@ne_|3lqgTuqq3HesH5s{5;uZ^-M*RuqSO zH>$lkLt~5_xVl`lr63^{qhy7fa)-S@Nn~<>3=61Q(H%W6T(rEGHf0u2jIq1=rDLJd zRoXAuR=g7ZchQ-qT8%Jb^?)sfExa{mH(R%0(fuK&M`k7JPWs(?$dx2@9t_a%~w(ebX!d9RTYeJeCIFRw=vY* z<1*lY7?Iv*cHmS&{_3jB;bKe~N^^J!WSIs~j9vd(?nbj){#9#L=Ji0^fQfjp+0$=C zCRVm5WZwt7_}6Poa?0cZ%jK*povzvn+fh?PJ#_{-k@Ayo=ElJ=`=P9mqR4V1*AMeGgOdCfgPF|slQRxlP!X0rL8mZmlf~#$`09D zs4eztff0J>%ojSEse0C%hCpCXT(UfeCM4E;6TMH>xY@D4XzsMjZ(%}05p*{IXR-hS zdXm0~yQoav`%wXC&t@cJkzs^9?AbgGrS%IBd9YQN7;d&^mz&F%rcV8&C)_Q9BDA1j zT+25ntGD##%p|C5xJtw-&Y~c0K==C(1A*!#Kb- zPgi$+jgpan0@pjHVXUKSpn#~qlrSS2DIVT_-kgyTcvqhH5I2ul(3TniT?VI|K5ti` zAG&bqDPupmtTUiYU$&GYRhP74#rucF;j>KwjTJ(5Capma$4G{j3)^RDIS?jhe0Z#m zXUHY=B@CP8-=&GB_oq6M~`_PAD!$hakDx<3YCvO2zMqwB7qITghP-Mu3} zL)TT2qFE^ebD0Wm|T@P4W-xt(ZQuRLo^V+uP!>PcK!TXDPAwntw0S?LuX%Gd1D&Z&A;N2=z~5 zjU5c|Wt%+mn8P3;ku>4LR`Mz&%Rg0OcPa#i?W%8N&%-kBzYpQ&c{ke={Jlkjt7wSx z2C#%9bwzsg06!(_+V^SHCvCnw-d8cCKR>!02EF}}4ET9rpu|R8eX+)QHiUuR1pItH z_Xcr)9+Bqf5W!}l-y`Ae*_}QInyk|m;Sh1G5zMYFqbsi*QgK_~ zqD4t|+kmT>;`2&{SRv{f{4o1@8?fkyKys|8#PONS{Wpa#KqsUID9uIERKVQZD88i- zI>FnZvLCZgqQG0+XqY~J_VMmdS?VlGBRmcKY4;4c*mE}9S8B9hUkfgR?K=2{))qPsB;I#N|oYJ1N2B&Z~zx0tA!(h^Y3$K zYQ(aQ%V5>+vqAT}HI{!D?Q(#lP8#cPuoE`k)g_pP6@Wur&%B+L}^S%kdMQ4y#Q1m=lLHK0MaJ97@t5Pzyf{xu%=goJwN>skS1y_vFUG`t5hz_ zrLt1_ijtN9DvxNgb7OE`J&b`KzI#5`~Ker$}{y%8k&zD)r?? z?s{GJ_KhQOb~KkB8(uRMPM;FdtE4HP+gz-tW&gPOw~9k(bwDcXTY+l`b|_mL%k;71 zb$bn4g){*+{$M?O^7K3mVo;5B!mdtPox(l$X4!d>m3vu7obQgP^y%iWMkc~C1+x)J zz^j^(0w7F03pTpKp3G_?o(!5=1kX!XEPkcHX#tLbW0<`!7zN4itna>_DK!%A+@e{W zAaMhA-G6dU695#5^SxPd+sT7z=q4P-2Mzpox^kmOei_DKdB{qB`5X9kGzjllr=$)k z-w9?&oUmnjQaBOHSZt8LUf)&3RwbrfuwB+UR5+k5Fst7+{fZ)Nc3VY?G)OawuEr>LB%a)0Z&jO-ow*^8R(WsHo~nkRc} zHua^wKtDms#JQC!kx;dgEuN32ir&rIthqVDvV$&~q-6U>(yml_&WCPEDD&lWZ>h_eK`~( zKX**)O(v+19&`cO$^)J;FxD`m1ZzC-_s)k!6JcJDt6LQ|tw@QyqZYu794n;W~K-ivh`ZDY22M zVj$!(fQmcnqKZa_@VgGZc_8J1jnT=h2TL6JPcdF&!#1b2Ronew1Dy$riqV|Ll*ngY z8DN3)o(9SaI|hnQ`9Xeb&h zV~Nb-_n;sc!lwTm&zZfIVv&v?^I>kPMc4RV*+B!LVoQ%)r=7Bd+}vE{Q1%lpC!j}8 z8!>&n#8n5LptPY;bi!0uCoOGr+%;QSD|1o-`I(u%g!=2W4BlBYAAN!4gc(evC;c-_ zt?!GPjNPqlI65?A6&-Bu*fog7KApbfuqR|Mq0+iAkKMnatuD|9g(G0wz$qL-hg*4P zY_5aQmpmm@R+mty z0IJuq71|Uj+I^O-ZQ9KNVxR`X%2$1@W4yr>^yWFm*>KMtQ{ zJKiq_sO|Do&>7~VIEk=mry7i^r{($=*e)HJ|to_U(oewkz`>dH(Zr2`(#I@y;h?hblw`900g2rc2gqEYC=mYJt%n* z4v#(vuHG+HP=TcORAs(;clPA|P6yu7(Qywpg@F2jvvylan09g6D}{AC(Wk{9|vFJOigi)i8^sFh042nJsRoLb~b|CTF#yCeH`Rh-jaoAz;&Vg);_GZI@-s5{s_ z+*8#!W4cQp9M5FkB7q`Lv-t%bD|v4w3Y z;vG#hoXuh;Qc=JK!mkCa71j)!A+c{T_S3vKWLl!O_y}WR0sYMc9;iCm!PJKb;^285 zND69Z$!^>s{uIkL`13-0DSTGbc2F;x4%vd}Pwc>eJgZpcrvSys40Yo4)?IwPWo7QD zbVRW~4yRbF^AtP#EucjBObi0VF!VQBBBG~?mN$V6iUw(Ykv+O6ivD5 zYq88#i5>#>B&Yj%M0p{tQ2J#b@32dB)TI;uiqw~XqgN*XmYk>Mz%;#DtE*;lF&Is9 z=->V|ZU2t(7yuVKeJ)AxbDsDvLo=hfN`h-9oy(KgHoIj}%2+7@#-ANc zujANe|G@al)1%e^4NH6}H z;NwgCkl^R*t+sVtHT)SrQaa9z)oeHm`tRFwZfkGT)5?EN5jR>XwLJ9V`J_d8Ki_6s z0bM^YaLO5;8PFVIq~6;{Hu&vU`Gz8?zd9ck8Y&Fu*hpauCZTT^^84y}h=${OExZ9N zveG=y00O&T!A?_*uI91MPPA`7-zl#1wYO=Y68x0O7hd>r=m{|oi=t`{t*n!Gw?D5X z@b-UD`$7y(aC@P#7te=a`J9Gvx9TN2jdayA!!Covmtr%Gvhx<{-?8u?CeDK5yH22( zDYMzUq%q>0;$L0*ibvy`ppR=V%z#19$gl&20E*V`0^&M-)WoOQ-L|L7cA1 z2UOK4PV2^Se8<(X7~oFuTuK-46qbK(g6l@#tN*TodvYSU+$}Pz=u|lj%<*;?)}Y^y z5GZNHZtCTZGBHi9pgl9ywml%g^5!ZWo>7s^2Ff3Dt<-uRL@P$*y>k79;;|9Uj`cWkE|9zrLTQ-k6&YF9rE;x%gy#=4 zVYB@;^Mma0wYk`NxmY?k{$P8)9yt2a)!8v}V?|XD{g7yw1>wKIyJ*fq`ifJO~4eeg4ckfKFKPQ4WBtWT`xam zL9*{XMKdXp(Du0leDDYnp8BTT2aNysRV{4AXBac|5@Kj0CdF&2`q#X3^Pum{Ilw5} z?_ai-jnpS40@x7R{Hh-a`bM^Nfn6Dh(g~+^;nsb&eYQRdt1sHPvTXj43DML(;SEiX#zo+6nX{0_qVD8cCe_BE{}E$|8g~ zMf(f*#iB{GX)I+3c36G2$oS;q#hIh_-h|f*+@nrN+1TZed^UG+A$#hdCBTRzPsbG0 z;3>4H?jq5~w-xqAKGJUpS6&4>{#ckV%0qoz$6EkAS6a{~HT^@`dV=@QGV&&lIvm6z z32q&pU+^YUYVfVA`GexyTw-hc83=o8M#q!d=;nxDctJD2Vk-v{g>I{Vmwfm;YZGq- z*(J|A&$UcMO@z2`(un&;Bp?)IakcSMw`QKxoJ$ht+^#dM6C$L0+C^b!Jr1gbrvzrh zoeA>xRZT2JOaPh}6=$as>&Gyf2>P8`m=$~`t%o?0yFaa0hZcBGP@kU~2_E+EHazzd zFC(sLjTbUYiYGb?#S^P3@0o=x&l@-TU<>vT5tO|kX4~Fmf8owAZa|1C_8Aj|w|Ojh z`g+WzK?aYnxsd5|O2>x52{Xdff=SIs^`z!GxrUcALDyXof-cY7zq>9d%RfaQl`U<} z_0{C%j^qWu*#!62iLMA<-NC6fW3@McjT67DeKiids&?X)<7%5-~!Q=-3bsOjAb`Y=pfzpUbq^e> z11VYQLZZUatqSNps8-cH>sWsHfLipm#F<_M)Yi}~rX07{I<-0xV`ZN zR)=}m$XIhXE~h_psud-vq$j|oF+A?h#>q_~+wIG^2GyD8UU@!P^-QX6VXNe3&FxLe zr;<$tIrq@GOAHM$`a|98R=2=F8iV|Mno>5b!z(;9u63w>5LQQr};rtAzMfK zRU)gz)WTI@D2n#^cR0L;cbOqTV<|;;UnWiw%eaU4c+@e;=O5eK&2w-uiU;6N4G6k* zGO~cQ{VwLp*DNw_Yh(r;cHRohA4K3@I003htV;9d*vr|J9B+SxZ2|FR!_~NDrfdY* zw|clY`0dGN9GHEC>eYf79h5Q|8LzLC@yIp?Mi18{U?ioafOy>i&u zW@k*DZx5qtUj6yf)F))ZfM5;T$hf~4ksC;+kz7lBL;TVhff!gM503Rw>)+4Hw*h=t zj# zC1%?+asy*EYmR?>qO-u&<=FNl;4t{0@{tJ@KT4=Q)aw_E4oUn&xr=@REf@76jcrDL zAac~Rq7KF9x8uzCFQ_Uv+EN5&RHt(s^wdE(F9&P&8yZ}?U z;0`@z*F%|09vhE$uxX4DZ=5Op1@^!EQ%l}|aL*k7ggr4oUZt(qTsf}%f#~Nhc0g5} z*>pKn;TdB_FXfF2FriMmmjzf^zz0VkomVjG>us+ks(RM1Cm0r*{Xh>mewS=>%e)qN zRYxk**+Kvh<}zN}e}S)njtMj-*m#&oDSe)y6hA@@rGaT4vWuiE5ka0oG-L83(jA&G zw1-Z${KlNyRV%Luu_G0CEd{sM+xU!`Sp?!BbUetL?(6|E1l@5gd$$;9nNFAPpPZKI z+&5Bei4;DGaFx4AYR_N-Y<6y^_i7ma6vB%YZl21tqsYYzQKPt`a*@JVDlOR*omVY{~nb8{4a?SOR9e^E*XHCmGOUTf^-xoEe9D9yDn&+({KZ(W&UYP<>P+y6S@6Hr7Efwcdn z@ckF6@eVayGG% zvNg3M{7)#^Qv0n0@Ie2SQh|#w|KTPoGl>7whshh*m@xeJ08(vD;qCvsU4Lk3vQ)nqEO;31 zzA+F)eIO7ipppN|Fv!1N>-W&e{tbjV^)5(&S_btQ9v%`FY8f8#ZhCfd#bshv3K+`j zC+?eQahl{sB;_s?auR_HfBtsoNnpdby@CEv=^cOUhfn?13oQ0LmKY!Hm%6w(drx1R zY%1IsqXNMA1sIqFR3MNN6w~jsUw=Y>3kMwz86@)_7hfr#Q|*#=Z)vwt>29> zCh8OKoA1T#^=5OddxxYKkw^uLdTa~x>&ckfP_s@^va>WnqWq$t8PcIzY$82A# zrAxIAUE237AujfMgXX(Hpt1Strxc4&K;>cop)4Q{JoXVq2~9Q1H-_vG-E|bVDtVZ&tlJf&O0)aFVa3=y9)L4PQp)WxQ!%cm3kPCffl~ zARUSkH>1lpdj+|GhtD}>{U4vZShC9bmqEeaJ6{B|pXraUl+&An9r;V|Jj%mQqS?Zh zTVjcB#j7a-JeJ;%X|s=PPJbVK1Pug)omdWHAmCp>WdwVY|5xh=T*^ic!orctafwI* z+vhJv4MErkG&u%~^gpR$P5n$Wq5I5wQVqck}NNm@l+>=$1kH&;dfQ zYOGb&$cvV2Ow`a32+Tw$1B%&aVb!XU+)`{<*$Z-PBY!o#aoG5;_r(-`ZZ^fzre?lR z1YU9;dVg+u(b2K`Y0+gKFUEOo&W8-Bda%IXz)7~pX0$RmdJ*l!gA7G{elU-qo*IL6 z;)xWJXhs2)HsfB*L)hIRPHfI;q7+h878Eo6lNwPHAYj1 zFiaW7>Ag94XznNy%_>1j4jLPF-s9t^ga!VN58wijF2yJwG&O%PpC5Ws%BK=$Xr0nc zfE$w-CoR$EcaWLJ7NAP8G6#?2PA*HWX*0*48%dBvxP4IDc^dw5Z@+hZxjj>l&eNa$ zQ5Waxu)TWMs{Pzfzec-`ww<^0=v8>P!$IZZbh@>J_^~kmnqvsjbwA7E7`V8Xe?o`T zOLPZVF8%wbX@oPH12|Grt|bL5bQE)_fPhfjt8}ua;U}=B{AnSkXHw6i%c~Q8EBY z7+t~*7y((F*R_{{!x~gaCfBJ|t%%CH;3q^2BlGjxSvQII`1RI7bGTPkNkp~eYczzl z&`3@RO<-xpMxa$){VLmpS_oOPg#Dy{Sin&$s5MG7u zPQYwxxDU`B^&0FODUlql2r=K~w6X(aCUA&li+K@d>Ekgyq|EL7p$k@mQ;3dUgdce7 zAUnzj2g#Kg5F7zfNpN*DLM@ZzGc+oE$>mB(XdCiVnpR7NqaNsJ!g*n zaRVp0?xdIQ<}i-pyBI|sx;AVUhI{Os@{G1sf0c2f#GbwHdsqpNkaUN)S)fdD1KubN zqRnrR^tRBeUd|W4Co1&i!&v}(W#o{>u6K#PTJSwLB-)9iBD{2b3PShqnk2d`m9kW} z_M$E*nJPsej?*3FTdm4;FwV{WsgE?auM zAB6|R6(7k|HcI{Y)A9lz#g_%E=%Ud@csI`RUeP}BH~6BH$vRA_5s|J#q}F(-^|YOv z&Pb_)u%7E)30~@v;uP&e_HXUxN`!HW4Sw*GgITB*NL%l;wgdX>)AORV*rnOA*AvFB z50tSf-=dXi3d z(_=E-93F{J93nzqH16KHU(im_PO8UrllL@}mB^1YAg@o7;^*qjsc0OIh5X1cly_AP z6&wWa^fI@k4*{GLx;Y|yIsvuNp#^uxAq#Gx2o}A(uyoC3X^i zM$*m4w}Z5mAP-R6j*dU$P7wdHn>!WGk2v6W#uoJlNthpILh7()z-gjxyNL|zh;t-} zagFRm^93Evs%98$HWKc9Ls;rfl(i$0{?ZJtP^P}knFiEA5xF(SukNSWaG>K9KKJJL zR!RKUep$`VZ_cM)xl0Iacgf)f30oANWBq^#HUJ*(uS~8E(6-M$tzb++M5R*>S$^A8 zn>$gNi^8VR-V)w8TrE;(`(|G%EZbLvMgXlc*VwEfwsf&(09yqa=(^c8g^B7hEC>xZ z#;bB<%I+>T$m5I|x<(jClnAu%j1ga#V#0tX3@&j;(iHbRo+_@)zxSMNuu^nV*-E6hH zoyc3p0&P5(8*P*lSUd%>`0OpCENKwf#}YF9HgLp|;ludloFTWVXRuJLnz1P=4PI}M zH{8=F`um&?U>zRaGbLR$UG0GKIOs~UrD>P#wIIJk(Z&uN!z;c=eQ49VvFSFL`QtHM zYY0d|#W4Drtdo*=>mx4 z?7|AlpDQ}yuoOqLjV5Je&}?f9y>$i-#^$~l!&E@BZlkdxGH!p)n5d9#Y-3Kx=iFL_TI)k1(Z1Y}_8)iBrsAZ3a3$=tX`p`$jLW`jthlwn(4RG`MB}!s z>Y$Coq%$i}jWI*`U10K59ssO4aN3rkm6BUt(O@Bo?fydcHqN&;#W9k985Z8%67L}q z2=}gsSG#gXyOH4x>=(*M$5#&ENz3ZFS>l`U6}Vwd_7yiB1`6Q2LU|13D7k;Q1nKI* zvvKjz1@Cy3^OKOQ5eqAM&0xatY$4uRpZ0$l_YwfG9SK*rdt8OW%BY?u@8}uGz?dka(BKjIBdta-(tz#VrfU_ZMV zZ+b7`Fm>Xirm=zqg(#@=lTILWvf-LN!4dveD2N8#@Tjz_5hsZPeB+QqMSIW&V4Er2 zOYw$dz)%OQTKl~50(Hfmqg`wZM1ok}=h*jatva4ksooGp!9l^xk?~R;-w^WwZWI)& zN3Qj+FE(VdqaO1L{_Q#HgyZV_*xucc$K8vF+P0RWM9w6++ws8Z`* z*vE?6p6!ODsH`P$N9B?3IZ=RLa3qZNSgE8j_rSXeZF2k4Ni41_sJr&T@zzO&W_6{i zj0-Slh#~pU%v5O)mU=WTk_*{@l@6IIq3s*3%Gex3fLQ+yCie$ZWEq|TP4 zqxU#Emw7q|8Fdh!%+^PWkJdD*x-zg_pU5HhiT+QEf+t(USKG)#mIqgsHq#+i14vS(7oazzm3dkd(1SVo?;QAPWec6v5GOkxL8s!PVjL0V6<=?>H z2tikdpD<*<^iyOu5eoYcR;ANdQ~PgL)qjEf)IlHD_XMy9bG&-dU12O61U5;0q| z?5fwrDz)K3(}z9;Hfp*nSno(HAsgtTk}c`e!iZq*_z!$OSyV^K>trbN)l#TRN|X^B zObwaVK!s!heK_bXt>Wnmrz}lrjv)Y{MS_dxGlK&C&MZd^E(Sipj;h3HXrSg8|GgA! zBgfa$K{F1M3=eo7l5s2X(qLyYGf|1%?vuwuk#O>mXVa+}4&(U2Lmzzyd4dy{+v+DnGi1 zDnMTQ4jLz>3f6e|=IE{^VK}|&=`!@ygl+SCI7l? z31I2{IicE(Nc^h!7dPA}?Lp*0s2Br2v7;NQYoXkhAlE?SFbmyGY!|lhxKh_qAoc_W zo;CncF$Xd|0G7aCR5}LDc~l z76*P%y-ReI6G^FKeC}YOjEF~PY@(f4m{wze6 zD7MMDBb%PuF=6AaL11cE|HlR5gUnAm`p`#>Z=u6Bkd%9(lvO#+e4 zquicMv^noCum9>0&xqGXp?{ zYVF8TkI_MO5Zsv*K~RlOxx&5LvUtg`{wV*qydPdumPH=Z;zGTRLJ4M}QmmZVZ)tv6ePjgNVMU|hJ#KM14{Q{&h` zn8RS#@QH5Hq-={FnL)b^iF?FaX3@JHK#k7DRS!B|P6dA`f4F~PGi}S`P;djtkfnC! zS%=x#mE^Q1A(!Lmv%-C9=XB-3)`YcbR9f4b*S4&0C(9MmyD`Hym}>@sP{!1?X0{J? zpTDxZc^z6}2a7BUHH#_BkQGr3D3|>=QeAALS74(JT)^DGX{2RCHuq&yA`LTJWW8u^ zTGIl|I#a;5r;69{(&|L4|M^rtJFiLe1~}89unbKtq37ae<99OXy$+O6^696F*&W8( zyRE0CQO&~@*`O75o=#SqFKSnRwu9a%X2})ark6xJHCgZP7RO2+-R#duLDOvF_a9jp zURto&wDThz_XfEg-li5VFX#@e%b#Uc9onp^yY?JDTCFAvs5tiupAP_bYY!Ct2k+w~ z=NN--2Cr1K%;E;D=O!A##x9U!K7Eyom!Y~sG{*B zVc>~jFR$BJ5D7zsEHV)TszEl2s0cEw$2XBkN#Wpv1Db;C2&E@9-`43+5jE}o|G*a5 zo6^>smm4-E{pL_(UDp8&YWN@FypbodY;;~+eej;lG|2t-!J21(0q`v!eK%uOwZ#KMf*b)7>uE;PyMQ$f&PXrXUgyS+oVKuD#A` zcCFZve69HjEc;3SD?ru7!T% zlhlWXdXMj4X0-zSsN3jW8^(6b#Pq6X1!KcnjUR|{WyZVN@ZPQhwFuVC2RUiB5`@4_ zV3-T8kM7!XRR|XA<|lLzC8&}(xNLEncAgP^Qnr+C_~Zh6BIDHr!)!fdhr1%!TJO@~ zoVet~kqG7kMCG5}Yz{7#nCzAB1_r~Bvf=m`;zy8E>=$MS&42)GN=PADS)?AiT613o6(Fpg=K=-Hz3AuLQytt`&4F~R^Gv)HD z`A*2{i~#`Tiq*2!Bhd;^5yl0IEop@emy{W+su%w>>HfRY)A|6p3}eWj^zSo-EG;A+}wqfMOf{Gs&8Pmb{E&dqyEhq zBm);mU4r-l^D080ey*_$h%r{oAc2`G?x^peL5CIR4QG~N2hgjKyRa^=w182(P#wOe zAQ+$!nk?W+s5bYE>e00j7)rEDBTr*uj7sgz&roCk*Gs#Fc_Xkp4nqLCB6M!0aTB9l zC(|t7nmWtG$JmD~fEAjFH2$GJNTu1gHnZ8Nf@Hh|S|(Qu(FI<3^pu8Ppr zS?_)99wW-W8pcMhiGWg>9x+1?l(IBA4N3EzdXSbf5Znd*IihI8GbV|}0e;yLOPWrQ z0U66nZf*P1bJ+7WotsrbE1QB^xhP@SF~fu0W8_gW_vc5vH6&C^xBA7xz3MwDg$H0L zHk*m+qg-3_{Lj?XrjZn`6wP#K-7GA5RJ;pGSEX&{zNa#CppeH>9@W>9t{Yd^tefY) zhJ*bx!$l^RYmWM$EJr5|aq;aLYA?`+O`$2a5j!MULsLQT&Q}8y!u# zxd7tdk*qxsGltGRi)end%r_oB(J&yTCO?}cs5;k`xde^h-l1HfAI3^D^MlXhrqeJO zwg)qiQhI>3Q0@BaaKnA#qNnZvm7>swYKWv>Ah_Rc7c)ALmsqT@(Q0T}JCacIp#*Je zWaj8~H;GDGh=|E3&qh(UN8guf^F(2nuJrCcPc`e%nLqf>Fm*+3yOC!0xf9SL<|qp} z>lOauD#bT6|6x?Cq|7zEmb}_Us6`T=UQ#C4aOA!r49TQrpVQpkXhu@-JNvOi>$yWK zfc$mm&e}XADe)@GcV^_mSW#9j+6!TAW*Qth!HtKy(pf z@Vkr7Q*Ftn`~Lu9K%KuZQ$+@=@_T(Lr9x>zGUSp{T!e^%Q>*+N2|Uyrs5zNef9GwT zC;5Cfr5YH&>+SV;$~UK7aP(G&%2~(xd3_zIF5p+%I@YR{8!3zXyq3 zf`Q{cDHAK(vfHu&>7%YG!-{Lf+n~Ffa3!oCfptzK=o~|#5D!_pHjxdK*)7p8i%C1! z%K9s$+x*;Q5?tV^;`p+mN*SXme_pU;Ej(Fpx-gKJk_%Sjy)tA$h&Pyqn+Xt3q-ur! z138BSMzkBjouhEs+J$pS{{eo;VhX+iXqh5GgmZj}*o)u_U$JtdI-+YxiYar#%bqQ^ zv6Py>>$zRe<)C4mw|JyGKE(TPcJ(OYG_!ed#F#1h(_Hw4me@l!wO)Kmb zO%h@>Pd2nYZd_-usXM;52;?1(T&a$M6uXA8(MBiDvJE3K%orEhTd$k-)s@Sk;W!-z(W6zng6Sp*`j+# z^kZI2_^RbSrB82KyP3rGe--le3iA*wz{fpPYD?pm#)j=1ci0mU4@NKU61MR)!xWR{i=Ym zct-zZz~9o1hUW3%Y@^_6THYk-*4K4bkPEN0SCZ83tYZ}tG#G*n2Er-#ksu=?s(9ln zoKVKE8U0}@6bNFme-}hmsINF=r`@nqaz7h-eNUx{82>IRR01BjX3PlU8+7vkHbwZO zI5N7UOON8FS2i?Pc6MeV`$zHTQh4Sx zd?d%7pD+)(e;+pd8W)ZOHm)nxwO6HbOLENKT#&;OM89IH3znI+Y4q~g3DBriV3+GC z=$+l*|CezQN#e>yxMU_!NZN1=Kp`)E3;##`LkUGiK=6@8V3s{Wk!8ljU75pGgOM3B zhuV061Q!S*+0e`Llk;CT%mO&Q2xU;&(S0Iayos(Zf6;?Q_;st+hg`3l2)`j-iK{1y zj`^`HXs?O`{gA9^^Qcg_=?Aiy~u~^}hcxf_x~)LxP8h1P=vBV15U3(9C0)*5q8MB9&`EzAL-Iq&?6;puln7sVvMCW%%dY zF>gxYa`@YpUe-|~r9&@ms|k;?yh-hs!%P{~G?G)%@Ji;HTl^mKT!8r&?2c8ycPylea4WthY1#4Qp!9S^G?Qt$4vk zf6tEvs{=p$ndLq1HFo}b_lw?RK_f_Nl~?epymR4+RxmcGUp9N`d%*~=K0I39YVq1* zLHlv9BjUa3PY+MFf)|3z;f+=>+q)c2Sg-_A+Vt5KS_Tv%i)`OU=FO`zxzK+(B_IN6{wklJVk>baTlAbl-JIB@+e^Ea8 zTYzU_m-3$U+?kiY+`agc&yk%i;KbTC2R%x}|lC zfn|Y)&6F5yohH(1W0Sqf+A<~V4f}AWwSMpGNM(6_q!a|$RBP22xkNEEXIYil*W#`Fs=gw z-2nNaRrG@70;8r+s9c8T3}Vf-z0tj+V|X|RTynH0fOV)z*6^wW4-?i=$&_j$N4J3D zoJ5PEZW@;UWmzO*% z+*C@pwJ=%k>IS=EHIaJ*FvX2W-xL&_dAzqLq77}~hK3IZFX?kxW3R#0g$8lfQ&G#e zUjS21$G@PO(0DvNky?5p?u$%X=~TFYrei@q5WhFDA}5WGD?1Y%`>i zYUb?BHc1T|@8S46!KuqdFO$a}OhJeObjBUEN*OLupOcME2H1M=Ch7zWP#f#@Ccj*Mc znNsYIhVjA$DuN3d)|Jsi7Hx^jZMMB?IiPZKgyZhWQKm5>w$U;ie~+Mnb=-I2QU7`W z>#=bMy`)GNGw**}x65@Omgwo3|ykMVbzL6|tSg{=EnNJPtR?D{(Hoa7QuG8D8n z%>I;GAwPDs$kR7ZFb2i0ndXR6b0yH9U^QVpdKAfA&W8}}Vpmam(L8i4?^rJQN-%Sr zZj`XV0b1FvU}Wg4e~9ZXU#cH;VGNa0*MljfYM$qNf>sOkY+c6j-Dr zTQf#-Y2P9R(8h1HA*Z1xFrAd-k8OQ{rGP2aXaMk>rn=h-f1ybVPbW}OXa!yoq)CKm ze0M65gQj3Gru-sh@C_O{X;eMOgK#?lY7rQ2LsWTJ0T(BNM&jSnZZhQ8FK!D3B&lJ*B=YKrw7N?KksgA-qN|m2wEu9b8s|Bd66MN zP@L>n;1z6gHe^FS00PH()qlII-$e~44u07e#t4v0c zO&P(ZRpA2&A$x=Kkb#3VhC285qAAtf!WG)V0{;PF`!NXI2!!x+G=h)2lDiB}MzO_X zw0@2|#}58%k;FTJ={ZxO{rN$fp;B)kKjpaFwr<<1YeUqkYm8AD0jZ2)5zT`}l6SGd^M~rA#!#H z@XGI;bY)dgKGQ4j?HiPfw`pG*^M4Roe+H5P2NAbZ>Sc1U&Gu!XV(uC7K1{v>UKV~u zj77)~VZjHOoCj2K3<*{EEvi*fLH$>ZmF7v@7L5Hk{#^>q6kie&9Q?(j9B$5uIe=84N zB>`Wh6vOx$V$%;V(fX9(&Ci{pG`gO5j5@n1I9zOfY*q5Ufh9NpnF?JddIm`L!VRTK zno9a%O!o+t^k^#S5eQm>uz>kRknBnBF~Xz*>nYEM+KJBX2BQbjN@PPV8q|4FOe+p*451ahAj6rzN;w7g)Q0gijOszV^mkD!BG0gG4 zK@0hOf^CUC@W2yP9gi#Z?%G<0AQ{w0pbR7*4-tBa$4HI;L=lZp9!Kun_lb8P(x`R6 zWHHJckTU?w;-?1C3zSM;m!sosW%X}`QFV-}8>~H+YiprxL=o=vOQ{`@f08`MqWNR_ zCee1YbY*TN-;I z@){kw68v%(Qjbo{t>G$a%qlJ!w*z57$i*kD;#iwm`QqX@W4KUYJR7Pbfh5u9>cso> z;9D0R9eMFw+pOsIq5f0*e}kv}8NrWcdea0%rdi%-|6mMg)ZK(COt)kbnHH981D#mh zpuXtmrk2)ZYm45$03pFHUAcoFr2Ra-p93x=p zcSWNAqP<#UqqxrK+F@sh02^M5?OoWV1Onaupr|cPgHn}(R11E zS8g$?Qi%E<&Gi|GK~^EH26CZw z@#s}`CKjAIt$HJfg{O;A_rPO*c30=FPPBlh2b466gI8xw8_|lA6kvCx<8;^^I7)6u z(iarRDAwk5+$;QKU42)ot6oIu-{8~R!u5imf1OcB^~`GKyxQ24+=w}qcHfW;JK5K< zW?nbkbr?eZ-!n=wami5mV)4AZa?Q&FZP1Wv(Cwh9ZNVr1b2gOLPtsmvPW~i>$mU(G z3LU1|-fV67M>vSj>$OZfu!Abd7A2&O+ZrXJ_{BZEKU5C-AWN!ARu&ygzGRA(*7dn5 ze;)m#Y841SOR@+A{19Omwgt^K6by!P6RK}N2drKVFT9znFq-QQN6H{B|0Dt~@s2kUAV?Ysoi)sv5q2myw`_T)7)cHvMW;{1%gUzK9iho-@2JqZ$z_Ey zNq=qz>>URQJ1!?&cMWTPjlq)32;gWGf9H9;W(4y~;J|tDEGLqmtxG(;fQ)o;U8-)e z@Vnn3h=*hto*M@inKy;{MLZ-9uchvih8@fKQ6m|@Le4w^E>|P6pX&C;_cA79%je)p zdx++HjKD%G7W*huMfhsv^8+J##Ix1$`C0)K-^+zoyqJ7(h0rGK-NLow9HTejVV8Rh-X%rop`iQTD-sew0b_W zs~L_vdNv7h^$Z6eWTEgL`dR7E&m2duLVrFJg0t1$DwKCP{4eH0drQ^yI6G0#OwUV| zrf9;+cA4U-(x{a;KC!gMV;PRfe}4}1ylkQ{<;E$#^DC*KXPk@>u5ZZ5g}{LrmJ??h-ja`@U%Alt zB?_!7S;ZcP%O7C*i&Sp0c+B;LQJnCdWiKRO5V_)W(v`~PB`FmEZ6%g4f2jpa<)&-u zhm{qI7-ZXJtCu6&4Zp)|AQ5GvOO|V_Vd)Yp8sU1o*>Ahe5E@Ep18ZPXYgIE^Pa1cB zB3jrTERH?+T4XKvS9L5M1k6i;XC+WR&8q(ed_9H_xXu7z=Y4+4`)=v{8kV>4>8{KN z{hQDzl;&^Y?Bn>g?*dJHf7hIczKZSZzH=&Z1Wk!B$=o`SI$-7(xzb2n7P8Q7w*@<` zV6xirzqBnbi?&_Q5w`w6H0@@sXE&F$EH0O|?7P&lf zn?qz zITI)n#rjk|#gGgZe_Z*vTv|fj1q9Zf2nP#lRYF8*!ipB=sYJ~1%YLH-o7nEjCQS;9 z_i{0}IOBx`ny!JJzrrwt|PB!Xsp8yeQtZQBMO%aJKc0?o44aGBev zoCqlzVVd-~Y~3SFr`?S^mdvZ(1;lbplvtUMIfjU`0AUGle=1;Sv}UKyfVH2>RoJ`Z zG~3NQ%Hn!kx&_>8Q3^9<{2Y`?&NRy^_UN>Gs5r`5Zo=kLIB7yYwEv(m#HeBAiF_2Kh1@5LXeO_tYTNet-HBU z_j>Pm^%|`k^#=~e56&3{X=@!R=NZid1fb-HC#7&#uEM}}$v#%6R^yoY5eHENDZ5^! zDo_x&({8T8&Na{#fjg2WLgabJsLSHjv?eUCB=rG3f9q*75~_B+#?l)1osB)4dN!E` zeW3TjHRDx6l%+Rl|a9f=?f6CMfB@06>)VuS)8J zsfxZ_sB3MP)caU~_Fd8y@^TWH0+|bfUPIA^?YLy(m%M6<0=4ww zDyR1M2K&{B$kRUzPm4rV5ixit*d4)JG5fUG!y7Ie?6D03T}C0C_YJ?4h-DL!`WwK5 zN3cZT>urw3+Z1G^9_bP-6jj+toa+R`hFpYee-GKr;8SH&APA4EMsgEE2GxOJN^Nhj zLR|a+w{S3@#VrCo%ai&bx#E}m*}Z~MuFKUk6ZjKfgG7_vgrlpc9w8H$ApJ58shi}w zJG(Fp(JQicy zCI+6XqgxqPGq2Xqscvg-Z{8vQhL|(7f?h4<6=g-jA$(TikLd^0Q(w$wx zfV%c|@BR5+;Tey@*8~>SQ)oh|vc&TA$O*;E!(Xahr3y~H}s?mre( z&Q^c$gG$+-V)oTfPsC=P`zT^0*m%x!jnpU+_V#$}@Vv&!zDDY7RK+;#h$QWTc6C5o z^G9rbfJl_h>A3evLB~Hyq^IXXf9nn>*B!>_&FeQxCuUH>dEJxR5;X0s2fAf!uJyWs zh26;JMQPK&J~=0{41&}{6&RW#J5GxGIA631qdfy;bO9Z-JY#(<@~LI=oQsHFmXUk>@@THr|UI|MP^`GYJXJ}{toLn>G>07t{+rBGKV z3JW6#G%yqcpW|7=J%-5~qr0I;#t5GRr8h!9dBActJuO}<6(ZD}T{bh69fHz`gHXPB zfBfInS6_%!RUE!svUAzpf5ypmblNL3g(5T%^d1rPlu+QqoSQ)e1rj7?AsS`t&N_ze zvZ6bp%PzKvrq;O^Dhzyz2p@Wid}xfoFeOF8Kt-LA+4c7OzTcTUiy$cEgDjkT?(F?{ ze&_qX-}jB?PeL_ib*s97W?FR9idqnFISoCPOkdcU<>;YIWw!3ue`mETsf!SN1#@dN zA8LeLAk9~}-&g3eS(XN$V7Q$Jxwi+^FnY_dH*ks&U_YJ0X5yQlvG&AJw%I3SnO~EE zg8=2}X;9^PV`j$Wk6vA-$*2k-Q6GT;sVW}8mT9AH+qZ3JypScCa4Qj}INPc;0?;-G+2*T)u~+_R=Vir@ zF}cXSx=wkaf03^C6CQgSrKGd`&Dss64LHWzlH^C+Vre#yp%U4$U8DLUU^7LIsy|*C z2o=dY73{~Jqik%IxNQK;(X`3)ejpXy5f*Nb-(L57^Yx6Q`#eoPR&a;b$J%j!+?g{U zrA(^cWbkw1JxBA3tHqevlEqPm#rXMU6P^>auG45Ge*}3654-@}uBJ+?#;Yz^`<5Uc zJ8_C}QVjS4AObDG(5>|RCWbo_1IPU48<~^s19@zJ4ChJd3tc+O(g9`BDR|zGhkEc#CojPA}32;b~ADHV*xK7nFIg1VlP3?E&#`-1k1bA|jz$i1>tizq+r z92CmyxR&QP8lBF@;QAyD6MZ3O)W)TaaMuxk*O9TK$A^B={r8@)db74@MVtes+^Y8t zu;pVbJ9|_w)pc*+WXAV#cl^1<88Us$iHH1Fe^aHPhSqA7&RUSY+S-(FXMa7DQCSrw zK$cjfVJc!e%+YPI7=z#oY^?NN`P|y!(qXZGgA5l9rMGkLIgp>Tfd&)_W=0!_n^ll# zWg~NC$iSq>P~~!8QK$Ye5)L7Ss(^m9IMfF zf8b1lca!8C7|4wrzyrE22Irem34Ed?fcIW2>>qVk-NF_wPMvLcmZP&}6oE3!EbPqC z%G$1QRBPWgxk0@UJ3~AO_r$-gWX{8T`f*Vw=Y@{@E6VoZ5t>1cMoFj8z$YU|_^us3 z%_Z9STQn>)bVBm(sxl}jk1Oio6W+RofAX!PL_(S^)c!onLEI0pU19i>J*;fki&C6H z#m{nGD6N!wV`-yeIk`ybz|SJ)BYw8EsC7P%WeR(5YxAujnL-#$rN|NIG3*?(uFS5= zX2ERQT>xtg;8q}xD9SR}son+?uQO2)8+yiAb;rw#Z#pz9w%9hFT@Lddi#Yu#0)Dd6YH@vS2wUSjI?X8NJLnLC=5v2J&>mgnoCRx zD}hs}HYo8g)^?rTM77f?4crLZe;`&FfBjCu#SU77K7Mc2o1&%UC=c%k+{CLMAkq#v zyz#Ca%`1(Rjs0}`mGh~~;e3Z|Jal~Lq2cM`^e{VqogfLEj9=rvxPUQI8sYIX7UN^7 z(V_dpk#(`a;V9DRdKZpN7e^+=QPjneO>q@~4XmDBv3X|6$W-g| zspi^4z3sR6W+n&vT343-1}DG(W6GSDF$g6T1Tr)=G?%gA6($5SIW#qw4YwjBf85){G%06GyF8QBWKuBc2PT z+HoY)SQ8Vct;UH{yH=~Vi6;1d#mC+CqNo3N?gGxv{^vjUob#Xm`TfVi5;`%5!;z9d zZsOz_(+5rs{i?L2bnx`TqNT+Je`Q$d8%=jay$R9Y-MmFsMXdPoi<+6!-F!XCEKlCq zdscD}*2&=*H*IX`;^k$(Em}~XadcnC&>=4k$(UMDRuEdgxG-Zv$-L}A9n;C>^RqK@ zi;FYV_9Yo*g-Z&{-YT4*oil!h+At(ze&L&pIq1haJ6NKFJ?CM480+U|e}gnOERp?; zvC)i;No5Ndb2C=X9NjWlKgR&aAkRpa>z<@dPn^x>vVzooj7=f)*pJ!E>@{|vQ)=fm z37ZmjYB}0ySGjAW`(T$zT}rz??*2jd>gRvmYnrdbx7PRP-g^T*`Y!5Q*|#S1aORoJ z+gaYM0a>%N-hZKLz@=cpf8dsEXO2H-R8B?C!JIQWw}!AGJ%{uemN5LnD?@+!;mE9! zSAO1@>&x9Y=E>Lr<7SL+{^i(-)sr7jS^e7QGgzoIpTZaMT7FW$q{s4HGY95x+#H+g zeKIwAHa68Y=vD9GeCu^7hk%B z`GscvC8dq^nAgpv-uc!D?UeI?IYPVQtUjS-JB8Uxy8$-n+;0xm#ybnGp_SP7bey%oTX$-qWKLm7`Atwr)-}S3<9bahhER=^ zm$@!kFCnCC0p};uf5y?)8=UW#@-DG#urS;mtd!B9A=xV+qlHL2LAQjNWG{zVRkOdU zS+XA3*`EZHbi)=*Tm!h7lJ$l*J|2=R16z7L!_91x%oCyci#XDihsuuor2H3Dd?f0n zJQE=m?*<#@OLWdmlMuZ=LctcTA?nk)#4s0F-bsmsQJZ7eq>8%@&PX^T0 zv5ibm!eN%ed8$1$O4cW6)Hl^P?LJg<#9brVFe&Yu*(e+b| z;WJnxnw4dLe`=!_X%FiIFVGbsMQ6f8bbohpA$g4iCz1;%``}Lwo$H&VyccYMzbTBj zgyI^&)!T8ASMW{c#JA6IDmbLlf4E*X$6YnYj=20sm`x%#9>G!+r~i&f+{N^tocqCs z6pL)q3+?P8aR#`MEm&otyb40e`8FsAB~Qx-L1Uqme=*L<)yt21rMwPJG+ccrqHhWN z!&}H$T>KcW?8)_XT1Gy(xc<>Pn6C%OCT_?6E#*^1{Ozovbd&N2VJtzGiMsjZuWmxD zm+U#X*cmjoQ>-{wRNuCxiWY=Wlsw!8dy-TlLAjnnxZ7F!n1FDmMEJ*P#v01{h`vg) zWZVzBe@e=mSa&1bEkdNnb-4qRV)%Gph<5_-sFA+J4PTb#F}>zFZ?1Vg;_{fQ;F+63 zY$Sg($5z^`d{1<1H60R0EqTSum71iM6UEt07+V8dm7N=_mFLpbp7&@|m{m|RD;lJ|tHNHoipd78Ie|e&Lu{XS}jwfFoFO524UumAB<`1Od zaa^8&T=+VuyhWZrEewALOSO-vpF;|h9~UYY5>3USD?t@6uBw@HlGPtKnnB}G`a#LE zlpi5D3HJGg2q+q#r`ix?)QVcMegEcW_hy1J=GY+FP~7$t()*Z{7E*qg63au)ehf3I zf9meZr*s=?>LvvGQ867{3lg9g4;5FttBa{bf?^X{L#bFG<#||U;^ZA{{g(59qVahP zmap>Avf^dMD+^c8aj%|JDdkBx_iq%D=)e>yYp~~jnB|s{<5Xb3<~s3b>}n-)3~4XV zBXKUlR)s?;Sh=R|yM~W6e>)EG1YP^hf5YY;-};5?r2H>FT_F3dvni7O24;1G8z;al zALpO?KgHMvZ9Wv*2+q^@lQgLC5QTglj!QwY0gK}EBxKBGR3m9rWc}6JO<4X^g&E2{ zjqvRsQu$Iu?SUXM%&JwEQiAt9?HwESowl-L?ins?vGvk{>E>`VL2KRZ@jMRPZ*or zo7AY<-})vbRRF2*Ak4~l1$LEFsbl(0n9U>1`yOV-p!9b(de}(j2istqZ6l0=x9iVv z4Q-GY6s05wE8l^{Ibb97ZNX*ne+1#<2xP;|m-mJ?HahjR^}uysvYA3$xOhymN#sB^ zgb2gOsqR6!<1s(_(yLkpB$H8{!fbP=j)w&_wzO>QHlg4j6FVqR(^E!CEuzQRdw zu@&0s*1%Zvh|9{i)@id&xafU?V*_ExBP6au-VVL(c@kFs7ZkJ8mJ%FreVJ+r%l-C1 zKztV$0uTvb^=G-8?SkpKf3U{A#(p-)EBM?B@;#~MiJmn}yeF;n=vHQzZJPOS ztK^(n;u>Yfyw)LW1p)dWj(LmXwVVK*6IHsjMJ_(4&b0}(3`8faoaj@V->24x$XQ{w zrE*IpISd`yf+!DsZQ145#sM2;E9X1by4UX5Ni`W}wQUjZ8__pxe-;5jNSTIMc_KE9 z#2Z@&m#mN?XjCDx!d+zt7@0+d)t_^U_!ziCHSb~2J;L=Sf0G&szJ%D3o1XuHX3jNt zowjaRw_MjYXaE_i&}`KN!>o)lPKBx;z>g)v&*#HzR@(2#66^uUNfX!HL{DjB?KY*l z=E`?gQv7aV^P~2fe~clEK;xBp6eY~)p4AI$~xCpd4Z0IRplZLZ>{w>8~+g5D8C z#Tq;cRCm##ilH*pt{|JENBX;TNbOPA38TrzFqWxO9ZAuzf4xKY0}OhB`~e|8R-sfB zul6w8^G8%;NKtyizW^!S{!e?=#x`}G;mb$t%ST)Y@c?_+qp%{}bycTM+BB(BRZUu} ztzw$bE!xygYK25;p}?Ba)(LS)11RF7X$WqT0*YALa_lNY2(1zlRYj}9IyQ~TRm+l6 zSlK!{DB7IrrRi-jC;fUX?yfy4Ccd0Q(7C;U?~UvWU~3 z!X3_6`QLev(~ohOA(dVQ*IQ{x;hzi*)jxC1AeX?!-os4<*<&j#0~sRICM!iT3{;Q2 z1<4+~F&P?gB%B(aBuHCU`bH_@+_=67_d!fBn`tJ;DM6+yd;)=Xtc1a0r8w zPCYzdj~P%<)9Oq|(8lQLK$U}oamNXZIv@LfYjgvW&U+qEOKia)uEPaLp089($`u%h z+E?_m1;kdj6=RxwaSNi~i$4oGkbk+0om-MKqF*YiSFw%i<+dWP!x(iaF(bHYy|C+X zRSt%8f7Yk+`(k^;@UGn6!Czslm;^D6hObddkRhz|UHHKfc|&BKS}Y3V;#Mp4fJJLd zlc&-;Q;jk89;r|cm2bv-ye<$S^zX(NeTR2MSE47*F0eZ7g2>>z? zl1zjypq#d}e-3t@t<*#@VHY7xE(awPGnUG~5wmp-r2yuA2>_8#ykrprh$L;B zVf@{JWD%ShR2&k!s`i3Jn8moR!~INBIc3q?%LI1KAjZJocNV>au|9(<60rq?5J>1m ze^r(Ayn?l}z*a9|VMN`g5x!@n3hRX^3IF^&B^?s$trX0Fd!p`aLb4+OrQmI{z( zUW9g;d2X~f31{p>TZq4|88$x$*QaB6S-@rrcK;F_JXG!8M9o8$#F|ES$HOsWjFz{W zgh6vJ6URv7Dnm5tbiT!13hdE8f22|we*onUcSVDwx>!`LNJy1vwRw3xr8nB_yk5;t zVlSslI0+0UIEb=x({?Pf73mX;gy6mOnHP|RQxG&EV*wQRi?*2KI{94&-;L9+@>0-l z;J;e-hdSTmngJzCA$}BdEM|G^bf9_6X7(EiGe|Vx@A+CELEGYeuzDV|uZ2}Lf7{dC z)0|@{>}qs(HA-rcAev;#$I1u%(I{e43_k_?%tXu>%tSPa>QMz2D8>s8j+B7x?&JYG z+zuxH-W`PLI3IdRFgLRmNK%Ski?5eZd1siyR+y-f2wf|tU)kusvQZ9%#l!MNNs@Hz zSu}^*mX}M0LV;siRaTwHdRF{Fe+X)*#AaU>aik9bmxbE|u4o0*?wSM~u2v+g71%Ra zFZqUgAshlV;9e#K3$e)YQj-MTXIghiYf$uZ>l3;4mWndz>Vq3h(B=}r@EHIXlGwGW zEYEM+R2SY7x5Y}JZ`=0XWbbx!1SXZ>vuBamY6UcZnrOY77{1#g`ShYSe+KW2P;9GI zK2cs4J+96?m3fL;vzokVosp|8#~P{<B^eR4f3kQ1f5W7o%DFj=^7p6o*lEe=Cs%@=!ST{%CRcM5BNSD}v{~GX zTN~{%kp2smZdvQLtlcbL$Gc}GXoor_yY9uIdH=;YLQLoT6a5^?r(Zo1x3pwFLgZ%F z$x45kwXAs97!UQKR;5Kw!?$=BXvew}VerK4%U}xwA~0&u4hBlwJ}4g@j4g$?ad0T(h5V3>=X<-c(9QiG>}R9Q&sP zWv-W894$zcl#YOC2$;?#a~wN*iB~bMX(R7zW&#>E*lbHA*`mZ>d_zE;<#^4>W{zzp zfiWMuwP30_inzs@f5hV`9!Htu`$CZ`JP;!Jx>%Eqw$ zD0V)>ihl-w^7-$EN*2iBwz#7|3>y+{=p`G_QL+sL)0k4XYk6!Y55JTES|y zL|$NvfNGDCod);~@t%#eLWc!a#AG=GH;9!RZ>^2CTEutof}>1-kc3phGfd!QofeRI z-D0S`;Si3wq2i2f5vfTlunnk8y6?IE&U4|uKDfq%fA@4>vd?(dnS+oXA^Q!Q&IwvX zc^h{#_}$%>bk}5^1_2165e;OD&u_{kHf6vLgLdaKTUdN)T$6Iwx?uvP+Q3R<=@c?5 z?GHvD^EZW9x3?SS?@WSQ>*Ol#HjX6Sv_)Us)(Un5V~AF{&Yt8Rj=gQ&^f={m5EyOH zT#`bTe-AS!0#&jD)52dHVi}My{%x&-8zsh7nz%X3OHs;quOjKC&ux+X;a`QXx9+7 zQ&83fdv`#lcbE%EPnNd8HA!eWC0UiFMGjv2e;2v`N0|A9gw*t^1yX_}rG5Sk#P|Z< z5$CUg)FLn7Zl`rYZgNV@%E6PEJ`SrKWkGru9}8pi6L4w-Z=7QLX;p9{OrOp={jAPL z3Q+(*x&W6iLZA}Gc$DxB<+v_61O-%o7B4!qS;o@{CLmJ3t*b+kINXd$uQ zXqvz&K9*xuoV(>C9JJi}9$e#Isn+k%$f9d4#OZD!ARNG#z9}uPUawcleyPF}e?(rF z@`+02WQuq$A$^R&|8KX{RfOB*y8%%eprg~eel8(#E74D zUX(~<2}`K-i)_dcwgos&wDVXB7a9#LymAh+QXW>hWz~dRjW1K%?$_)U;fftd)X4)}rmx@PjAhed1?k|?l`rG|u#qu%#1%I#@ zj`-6!^QnK*KUypw^;`W@@^9(kkr~l)sObM7yltm=FRYd~fNiDMk-E&Me_XeUCM2M<5-x3tD3}7}OdlEh{8C%scbm|OZD^q@*DOu+= zc2Y+6lA843a7e|27qO@M1cG0;jbx;;V&Y7>c)gisWML4bn~fo)77hF}ae=ELH9_Eg#= zO%+I`k}6HAB3guw@)ctT8!%uBlw{V~BiHwPGiST^$J?2m*}0iFfA9T%zZc{~F4kU> zFc}W^6L8o+QhhYCJc-R;;;6WU^`3<5IGc`dl6a#IC2IE?h8gTI$UyWWUDdO z^vnEH##DKVKR<64w5vG%soWIzf9xOYGAS14dkgIB0{W||L4Sh3$EY#=AId$((gNa}IQ;h@WJvrq>EA!DJFmoW z9+qD4W}0j78ntG@33;E2roS_NBUn!3DlFW>S>Z;M&ZMT&UJFRFwm3;;i4?C_e=GqPR(=d0Tv5oZ(Ny&TIT}&VaF7X{=Pw}d7Q8%3up51epCtRR${~^V zt2 zWdUDXoy3-xtt~H8O5y)5r2-2GQ+MOj`xyTdeBX|5f6j2Bc!q%*n>_~zzJZayQN}L9 zTiQtw4k*OiTg(m+uc}WVvX2W*X6Wt~EiaMbkyM}xC7f$j=}L}Erctb4P$~YWYli)B zMzh=#MBTx(nn1F5ZM|A>}n?5N=r_eZR5%l z`rdnRp;s_)e@INlN@J=qrIinh`+=Cz$)KZ~e@CDbX}AM{)kbyLBBdh`4=KLdNJ^I{ z_ejLAWbS24^KY@{xLxd22C0HUHRYIA#E*TU2B?)}5kH(p z)?#}q_f%5KWt=Le$!e>b`EGv==Vn+JH6w8;{h2#esels~V~5l~prnb)+d&xDe=Utq zfuVFE`>p!@6!fXUp`#&%JyftJP#(FQ8!TcX-OV&|gFdwp=4}l4;{RH#dkRy5Mf~TB zv^x4cA69DSH@m;#RtFqeh|x|QWe|X+yNUhK)@>^NLRc-Ku#f^j%|d5KL_O%paK=E6 zUB{_YwgKg38hdl0rW35G6Iw_Oe?ips73roh`&L6nKH~O9_wrNWAoM-bN>p1TGIBz2 z(_6;I&1TI;)ClZu2+|6An8c*3jB!`tbV;$5 zyN=j@5F?hQx=~v)>?0?UDzj2$8kw#;2?bTT+y(se0NhLq?ufR%G@>4Ke?BaD69*21 zAMOazyHzaQa+kB$)j3Q-w1!h1nwjTnHBBplWQEXvxdWK%ZtDNy?XpnVpE$KnTK3TqT2 zys0_}d8L!GD}qxv>vOqJ5aeUvwu_vA7qJBTfytoyP7KfH!hxAQe+u9CAi;1(g5eqo z)ZYaPQh~j^jlEiqBj*A|F}EK1F06W$_CN!I0>}Ad$XiHy`J?-`KiBIpzGuqy4@-$U zWJOo0G0F62XFH4n8JF|zr@U(8DO2{L;Vb54d940l##`q0>6iWA8_lK+(Db+&&sJ7W zC+WK~^Aow>m|@2Ke}iv6Ypf@QTq`}>U+sIw4O32#wFm!vXs#UZ*Mg*0%A8yx+l_Ii zKgM7C#tTc2`y=F9V>ErWL+-Qvea*5dC^vi07~ePjIsP4Eqv^jO?-((&;G=W)RBuft zJ2L2v^iCM(vTNdAl#VlouKDYUvg3@ut4qjTXXxhV_^a%%elTAWzQw98cMT?sZYu^(V@eRMvskPzOKm4v1M84&j=AfXR4l2W zoX3Y0mF1v0f5%b}(inJ6c=Jl=7hF#OmXa!BkWCR-m(TK!7Ovxo$(VeaGy-##IhX@& zFt)?}Le`lXXJ_5cI*rDJ2-{d$uywXFo7Qf%wwQHO4Ow)m#H>DAg9xV2M^YYuLQS zY#`>MpKAkv(zU!2R%E?nkS0wRE!v*8ZQHhOPusTL{Y-P(wr$(C&1u`VZoglgxN&aW zA5~F_%AJvwkvpRHUTa1B>-;&BtmoFo)GbxTUgER^r%@~YEF_aKm)JwRI-&e7bi54M0%s5zSoZ!8 z1DXxjr|`-&s|kLFwD7OW6dBg%GcMu*iw8^y6tDl-z6Ky>U=+pSgYlmTZ-Pw`3Bl0b z^}ZO$m-YoII#Z{*dM$BiZIuCp=8&VdncCQ8F)rZTzCr1+2u5JKzh$1w(j~{5aL+7yXp^;m~ z9~w^-9|jB3=S&2s!D;C4Wu=onq+C+sMYQnsKRI*|4zzR_x)?*5_==MNd_yaT z_zr-sy7>i?j11;gOmC1x=0V3Uh<)-i$@^^svvjyv4G$uPr9?k0;vU;@BXM)hq0{&9 z`4_ffe=KU_^$bX%T6cdLfk9z#%W8kMU{6+o0QvaI2wc(S;ttxAP09C`q|uvIL~1M`J8zf&pWLhfVV~*Yotc zlJ?_o)$dm45f<<3tZSa_*J-MO3IdQxrS2euUn(i#5!rba#TDW&NhZar=w!4mf0O|H zzd4y*5ca%qFh4@To?~yRhk8S(A;+Qr#6K_g8x|x)_HwY;MEoMYc~+XdW*Hv($5?d;gKyK%@HO zb~OhtD+7Eos}O0;4&(`#E&f0ILgIH4JErK zh3gT*-VmR>_XELyH=siv0BTHh$8))L2Z)Qt2TG`RQzC_NveI?efI0LOMJ2k7?j>e6 z(#b)T7&|S*OI9K)%Wq-`Nl26gmIxiEzXJ$2a}0l5$t`bCh`n_uJFBxJ3MB)&A<6t= zoq^i*7s>?GUJN`p?-_8WqPx!W(V;5RKS{Dql1>G?+2 zk?i~=IaoMD?G`ex5g8*H%#0m+kytRRn7GWX@0ZQS;C-NZW%F{C88lis8AeCtbKoz- zj}gQ^mP8iD#eDRXtjt+l7y|&r#tlyp>++jmgeRGkvP5iuI!6&}9f#*Jpi#KGm6!*k zBUmSDj`mQ*;M$>5fV?(KhdhyEQ+^PdA>ra~$Pp3by$nVWaLB+`jUQ0~C<kOnv38^zYnU6unXN_)L4wyc1L<8;_-*ja1J zV;DRC=M|5gOciaiIZpq@VW;(@SZAAPR$)b>yO*s@FN*9O?2y$sR^O2+>6v$QDMYAD zEJCFj(M~))8RcDzQ9YPQ8Sx5D2-FnVqOtL6?a#yb3uN}T5=vWjQirk1SlRh(qAV4i z7IMsz-JX?LpVmKdU^0N;j3^X{0es4)jSg+}P8LWU4cl8Y6|}?T8LR;^75!t7MCK^Y zvHmEmf6L<Ga1AP`$>cohtIMnz8rQeVV5BEZUbx#zugf(l^Eb00tZ{+2y7rx)c_}nKxeb4%_(> zjU+XsThLx}D~IM9(<(f4@|9~l0sY$7Fox&>CvD{yAEeTf*7k%g>=0#}t8A#U&7r%EV`f(04fx1SAS_?KEOAp(OZuo3{;S6jlWW9%i9X;OOhzR zF)C2@KrF!XE3~H{V3K&Et>RH`=@-L*{$UuEShBo|m81rU{?==shVaQ!hJE%8owE1{ zT`ocG>C6MMbYUs^0ceu(;zoMH;xry>{wCv z05TN6a#*^kr~a*nsb;FWDSBClD+6Oo5`JUiGJgpON;JU-y&t)2VlvZguV?RF$#MA! z`F0Gjcw!fu4K2)R?5ZqlF`^;1Us-WVjxFc0Y*`auUoXweU^@TM{)@N=@VJ9|xoAy` zXB!o84XN$B5yDEgtrFw@vu2^;sV+5w%|XXj_d8gXm|Gh(NH zK)?$)5=aCLZg=%&Fpx3}Tue=WSK-;0yBp{*x^M+YvI^=cgqEPZx_5!5vFwBkUp=cqZF_ z#rQ~oA>JakKmBGX{-vluP>{Xcjdq*-Zawi9O$Yl9(>2nirf0myG4O@*byu(Y_2mGV zjM&?Z2$UgF09BCwi|5-#p2rZ|aCg1sQrcAAB)>ta^eznmCbmf99QRGh#f_nU4O0U0 z%fyzNkW7hUV)L7p;i4I=xHRiwgs^NQXRn>7nbv=ie0nY&}ZVNFf57(uKA6T}BdN9r|) zlssrSZDp!pJlAC2*-5mPQKA$onEXq|K+)Daz}JdJy9>pd64m3gGy9Arc{&9Q*aYQX z!ho^EgW3M*-D^!l1+_cPx;hlGC3u{D?N`4AJ0=k?YBw#L6N*pXN#Ui)!48t6L~Fm; zm+>bzY_3OJ&l<|i=M7UAq|VO&?W!uo=|40RtgV+FPKB`gPxJV>}hhL>`|R%bYIYPx^vS5}*5INwxmEo*~?gzkWf63doOJe?qZ9Ow=PXsh3@j8zLG&^ID5!n)r<175;e2V$smi5nnFo$DlVOVIz3MRF&< zlMFLY7npV9NK}iO{BrT!_r^+~8uC6VRIm4}VA7x*5=O8s$JD>{v5Gv6OQ;GHD901r ztvQ_?KMXsh5n~7Ju9?4VE3q%aycAEUek|(g#2w5BvfS(G*|Xdc=;Xo;k`}(I%d>Xk zrd9e!W|VzcKw8VQDeTqZQ{DDeFKoq-Ol3Ga6nQ5=u0+o5keC5&DNe_|brvMzi+%k= z@^4sLr;c~Woz|E9`vh*0J|?}$$C6MNNUv3tDG&N1-q8f8Kavev*2Nqqy3-dEV2}rv z^}My_dTb{=fl5N|d#r8L!Ng7VUrWV^HWFj)>9;3~mnqatr6$&`6(y9uE$aLR6Qi5d zwhppvz5Qectf%PCZb2~Ud=>k^&LqL}kth*Xn0zOOLYcI4e6ScjrR>J>jX5xor^>0No z7QOv-f)EdJAfFcR)$M$37lvS#;5_p$ZS6lsBS81Puecz|29kC+7H8=zo);*J68}j$ zMPm!6p0SvWXj|{2`mCGC9^G7jc3(9Sg1);O0^2Y%oywl>Bh!6MHvbK%i%jSF9o4(dPTYI!wLBM#o3 zXMitEF8_Sd)KYuA7`&Cwh_-oUSrkpodhbuai5`9YF9F*K%lT$YJHyj&i}g?GnX4L0 zP1%*E3#{e3AVKMlWUTN4n{zF7B1PzR2Q*?KQEK;JcL$AxKn;r20riVd9g=728i(y= z$8(~VQaMTnf#z3F>EfS-AN^-j)=1+crhpX%?Tm0EgR}a&uhC451JU_GR{P_mA6O>t zo;)H}{?f=$H=nGzvCWwNAGwc^VC5rjbA(iqUO2BgA^9zF{~uW9s4u!5xOc%=k`ALR z)|p8h8dbuO_)tlQ3HjGQVqR}VVa{xRl%Ft!qC2dG)ox#zymlcvH1px7c z)AntK)FepMauC`p!}MpnA4aMNXwpAhsK@oMWu%hFr$D5kjL#d@`sEBEWu<2=q&myx zSZd30$K`UZMg*Xh+j#dGx0%Mr3)Z<<(6ahO6M;N~DI4-NEmNi@Vm3F0L`%VzaSPFQ-u?0?!72u8@|==?HsmC9KT^S+_tU`_cqB5U`!o7s!UEd z{n{P8-8mX7ObJeQOYmxl)K@K%S4xmK3iH(&nd6T#hOq{K@{ZET^xFex1B#o3fo47MygloBgZ&ek(!uHe<#<2Krx|Vq_OiX49gI;8qW_Rdd@AKIXy}1 zASFMQVkDapo0f4c(_<9$z;V!NoznnWr~gx&d)3BE%tpdB5`n(&&@L%vy| z>$YCbO8E%G3L#b3FAG?6GOPgMy>Khb;VtcPdVN zr7w12Qdpl>vHj_Zkm%LfdJ02}h+Q5MdIMh>fh%3ZH}+6rn2YgmvFS+FJQE$SC^6X& zh?CtiBCveQuaLoZ0oVPU{~+UpJpTa*na+CTWj=so9E`uPVh|r}BFg=z!`=1d(4Y!} z478W=UcA)&MVF_IP|MGmOh8ad_0k<&o}uUTg;_+aV(ENy5zMe) zV;&~4nfMihTqA{Fr%XoepO(`RH1C$uGGG6a>EAjXktFxn0nDnf5>xmn9vab}Y0OfZ z`kW^zs&F0_bC%h-Z1C&JKMe0`=3x{xGtBzUmZ8TxFA!d}Km6|F$yO%RUu(Cm!@DBoJeo0G%-ERCftEC4#2n@ z*8RU5hzWh}g&!&iJUFsWxq>eb!Dw%|qm#+vpiWr{fLf*<)GI{~9HeKw{882E5#qe5 zhLr61R``5c;z<&v_S92KX}*lpOt=HV1$dl%fW?9c+&{{ZQ25vYG>d#G7r&#Hv6D<0 zN>$f|)@zU&Y7&OvB;Nf4@>O6HlSmNzB)ZR6BlTLWeci_B!uq$WB3$6kCSlc!cAm&_ zQH@*$0IrfF|1|!Fb|m_MUg?dci<`^Oug=5+X!t$oVSd6@pI(sDdjHiw%jQB^ zq?3=(KG5Jk^lTEZ5U67W26hVH;!#sr`3SXJ*22q32e6_{sun~X`{{JZjmjoXLr149 z7QE;c5HK6cF1Gy1JY)XpqPdJxMyk2V%9nL+_-LTYHW5tk-1w<199%W5u+1A*y+3&p z6)!+@2o$OG9&G_OT;gnB@`T&1qZvA{H9(+1+S1dv|F19~5(O<87zYOn<9`qs9Khm_ z6pZQ$62EmPLZIfx>iMePPt*v~)H69Tx4a5jvNjwWmEuP*Wvn2|D7_d{)`N$)6Hc)< z*dt8>u83X8a_2%ljttB;PE3V5zqw3Rl7q|+85;z(zk+v$ZRP3I$GHaXGUlsNRWqB# zeLB}b-*e3_)aA!uZuN>=r^FTnb&ktr!G&Gr6#SgxX?%AeCHm``1)nT?f0)s(~K z^JUAW20N?74C4Za`|t!Y?(mlPbrQuD<_x3zZ5#o8#Lt_N-E!|Y`7pJ<){An!Uti{G zg7fi}@8J0la9#17BlRC@syRgTJ0^k5jiBL2T zk%*{Y81^~56>-0Qh-A$u9Z|t73=97@QG)jpqahemPCj&OPwCck+4NfVnx=dEr5fRb z^Esi@(v#tcZfYa>*=?)j)t_i0d>Y-JA?tU0QDw7@^J`7PH9}0(%l;?=KL6cKuu@6S zKQ6PrR&$EU%+&AE27O%)Prz6~6;C_02w&3jX|?qC>Su6D8Z^vMn9r zIOPI5Ezu>B#z(ASGSkv}|8s2N>>EV!FBvRgx!Y%EIv*_V$%tXND89LU6Uwj~`t1$mA`>kR6>-2$rd|59SlP%xf_^(twHdIW%*a8=X_#8fO~xLqp;DfLVg$6UUf! zQq3coWOiUyiOHMj0RT*#c?a`@K_Q&Vuu4JXhKVN$mF8IdxO(voS6xRseCQs1X5mdM zla+hlvdUiQGBFPF4_j&xW#5cIEX*5cmeo*rlOK*(i%_%>TubS<6(*8mLJy$y(NvNp zM2h_be_q~Wgx(L7N3S@xLcB>526(8$L9w^`=VmaZJ3xC0FdtI_7P;fJ(EATF0>&2ZM`natI0Wf}fsc zZt7aZV)Y?(RKB2u(W)Avp5Q;&KCDCxtTT#D?9g^oQ9c?X+qB9yyqYuOH6tezgMu8iZnN6~{+d{$!>Co2&#;2o%E^HXk!$qTey_M=4(l^Hg!^aR`F77MRjfQbi40)KAS;MtBibJtr5e}R91fp`l z#&IF~YiG2eU_w2<_$e-Sa(?TwS#OLYZ2*V7nR=)PP@=b?6NP(?^Ul3;hpZzYTzDVw zZW6%*FbV2(vO1&%fY%`8tFR4;TP?j5L0eF7(I? zq6S?CxRZ;C+(|U*>Qv`>DEWQX65OS;t<3&3ha)vNO1X`BQg*`vQdQCsIss=JWgDd$#o2(Nj)5hvk{dRX(>AIB zAXITNG>-58bv<@#sBC9PUV2y&F~)j(=s=9Iqzf%@@3>SnJ2gUq;SEWOuuE;+=%hIi z++@M~2*2rx$?vLC74g>qCCS}-5DW4nVXvfg(*@=?;~W6{X!`Bw?dUKvG!YKe;=IZa zL!;|67CUr;kLUT~1IkYDC)Wrrfl6}+Frw+%+i&B8UTf=1s|#EF4%9KZwWy1<_ePen zQ*U6DYA>q4A-P0X^lqb>7&KiGQaB*<`>dE*!0Xv0e6fS+Fb_287Nh5#cveX+idQs^ zo%=epIU(QFc0#M)#1GBU2Ix-Pre*@W_MZu%mh#b_Qj1}=OLU0v0sq7d?XM}F_jE%a5Oge@%`7?xN-GSgYtvRMWsmhaMTX8ZBsZM7r;M3S}S>vGU)-dbDteO&hR%&0do*w-QcL~k9QbiS z>+vOSUV|$Z=>ZDN2^xfh zk!l@Y0-=Q|aqk)EG||9~6FnuDICWygHo6~}OMFkV7b_O~RR1d+aA$%{0bhxaV17OR zup7#vxJQH|z8AtEOf=4?E8q@MN7)ypwB5~7yK=d`o#OO9c?10*G8{NFV|sN)&m+%0 zgM_QVV6V0Hz-<(-F{aivUuD~$SnOJfqsXwjmiH7moe;L-r0+s7tZ7%KbLiA_pzOTS zFQ=mqj8DnNr?|HaxCeQ*F|U(jh~$GY$>;%&kN z3Lx$zBD>82exjZ99h`A+2dF(6@(#EqigeV)Y#D?5$zff3JJ~J%N6^s3h`7II;bqGq{{hB6zXys_!}oI_pi&`ko`8tpPWY)4MPqy$~1pJXEii$Tn)5cOs1v%pq{_!m-@mjTJR9`@b!}+ zx2WkNAlT}ie*7^1L)VEP&p&}LAJ)pg@tyijPbzGH07fJf#TR&qT2$_*oV*@R#XTWz z0Qyt_CK*>4OtwI)r2|Tt9}IP`z4Q8NN)?${)3q^GlA6b=0^&2cMYe=3ZP7oCaGFdC zMcf**uHIy2jp&u&wSIy~gco#`epoUF@w!T(L#9h_LzvZfo z#{1K7rGZVm%%o+gvH`UoH;I6Js@-D1>E0YbB&Q}}B=3trSP59Z87I2)Z*8R2U+~fb zKS2|*hJ20s_CaOgkrrSr_Dx#)DCM4LVlZZmU)bzMQCX2C;~54c=2T!st@(=crciAU*p>5BD-!d|(3ZtyE3URD^yhHQ~Z5XuSj zo27xbVI40gNRVO(dK>&zT3VK%Ar`f2C}9j$T3eMipSUexE|0ieS16orQJ6o7$qYWZ8Ecoaj2h%Cs#m} zBr709=*pqsTA_If9scFdx)sLyBm83lP`+G|33NpIZ0k<^krN;{wp7)1uF{DF<|TxV z=EV&GqiBL`k~Y*aqwmdWzZut{nnxNLmfBsp58a!AY?60Cnyh$9HmbD3%s*xTNvb@) zOz5<*3KD^)ZZ8EpDk=@VoYv@9*+Q2^jl`K8T#IbhOX&Aq65cVyaQEwz{nfB%#<+_V zlrEWnOGN!x2?d57Gf4H`%Us^eE)gw*>13&!D+mh+$sArp5-s|hZJ1`TqHD&{8*45E zi{4bEe1qDUn0KlEo>Kj#;61DbJS7sSe@&oIo{SBuMT?JmTZp?h20yGYNN0lfPVo6# zUncUg)D&)7mhQ@|c#*78zI~LB+XsjLf|lxN!tzYkPf_l($|zYf?Vn(&_#{Z_^Q42; z$P@=qf34)wA$?U6ZwTZ69D+ImzBt;FG^zt6m0#(~S?!;XegTNQ2z{dfukj|oFy!B5 z+o9+q1F)119P=QkH|}%?l-YgkGg;Uu)L|~`LMc2|;EhR+bfq69axRGRZS}sJVUbnt zbXx+n4PQV#sP3rqHd8*? z!xy+Ge_wTf7w$~m=Kf*^fWGxsX})v>C8BXWvy<6Z|6qTYlAtRF#Ve!zA)()P4~b^Z zi)eZsi6x9*Y|=QS{q`Vsw-(PORhj?{8Zg8%>s<$V(LZ#e>;ug$p?vjH67GM%V>&;? z=R5lxtK{zTI0orY?G#5xoA`H7Tx1T3_%Wo|2-twXmgz5mg$Ek}zCf%wHov6&LGh*q ze{BQDoQl+ylO|H(2Ryb2u^3@)EL>gyswXsjqEq?_W~Z-MsXWq|I*;kyy;mwGB^)4? zbmjQ*?9EsH?P~C*B8eg!n*4(%HgxgXsH#=p>#TTqcSw0?YLVFxJ@M5iH9jp`t=K_- zO`VC`8_>cFg)a~X%-&bD`Usq}73V_nG6S}yW;ywf;JcPY3PnM?4cly-K8hUtEVFRW zxjuAbY`>sZx=&xN7p&(*l1<~fJ=f0LKwQG|@3|7V2K10&LskD)QIy)Tp8hT#WgqOW z*?B-~kGl3mzn&g@5`fc_3W^xG z@wY6}%4%GX=A@|uZHCwji}-^oE*Dp&>P9U@OrSL>2c>#HQarbwzm(=q9G%pJM6 zpmfquNpPtEu*UIkN^!)RxZ2V)5Uc*$=Z3dWUw1|WO-kIuqDOjuQIy4qJ}8#8E+g$J zhFr$!hl%#KE$$h0Ih+W+-zXIHAq0%dG$ZLDFS;X~3IeU;v1Ib)O`3W70p>F&ShM-J z=%61>wA?@52O6ZRyz;>1&rXDaN+?1U*EQ&YHsGNFi*%QiwXyHyV2uBwneXq=%DD=8 zMdz*K?=oTUhB zykgq(J190cN#5q&sa>n{q|+_)rED8_7{%)fojK=|hcj!xja zMTGd@Wy24skSh^OQkk4A-eU9S({!rU&;yDArGw69swLMYaJiphUV6cyb>zy6iJAG~ zM#O;=)X+l3Y1fdE-G~KXr)x&_$MsV7Bco7h99XFkxg6CTA0%~~v1@<$OB&=FQAbaU z=joKTjnv$4sG_g@`i?8fTwgb9p5s6ke2<12+DOl{R^5znOhN+KlPPIM5wGtRuSw7W zFm)>s|75uuRGmIrZrULst|W@JA~feB>O9ka8>I<@os)Tj=?C-lj~;JF@6Lv9anUV# z?xp7v(^iHuJKKe$!IjH6vM3v~#;JZx5-N`)_N2W)oFO8wlMCcMRt$aEt)kD&;e8%+ zYt;KVxw^Oc$B83W=ok=hyU1x-BYntg z+sz*@C$di8pRzdsN98oj$Mi#Yai_~cJkv{WpAIRHx7qu9#-)lQ4I6%ggUrx!I1y@! zJGS2b0V14#Kz;Z(k}!8UPWHAiYVs5O7CCi`alt~JlHz`Vb(Or;so5GN;2%aI{IHTV zxQOYvDSJN{mmwdS*k5&EIY?zrGob{&Y5XW^b&=(3(Q;tQW22_ZQ*H-d=Z`-J80_M5 z5;{#yuJa_E+HX2mKKTOuXe3S%_KV%WSv6x&*nh&M*3vVEf50f7& z*^5zE{~LE-MAMhK)5#RG+A)oHe(urQdw_HtN`%PWfw@Ov_=d2lhJiDp7F4>|r0pN^_3QDI0*ku;W z+qPAiB^!v<$0~a6)FcVsC|ZI-HX%nY`M}0q4uFA$ zOV872E7U&Y0uftC0+=EvO6PNlrm~BknTb3n99U{V6h{J>|Gsmj@E~VN6>lpiFp-k) z<1E>HsM8i=rl@o+jYWP5m1U)eC2TCsc|70fK$wZ{9lWN;7iO>I6y`(|GTk^gM~-*^S-Tz*zL ztvj=TSc*-8{NyUa553cl2=~i{n~+vPC>$HISa*yD1E~my16LR8YJIP4{nl68@h%H5 z&_a^1Uix!UXGOVEk*AJ9kcg`qNIYl7wlmPPBJ|vD0{~z&N-@%&`bBN@9C>~QR1uuG zXux0Bt39hR}4_{pZv^!e)W;JMK$(F<$j_Bh2F580+ZHTBJ+IFWZ(O$g}qN^g=JLk(*_| z&?ZIuGX3pi_C5q61Y$65v-;(8P$b1x05Fv+EBsAzek!8-tzdYT#;7YStGL4KD!JoQ zuvxZHyt+VkoFoJ1>KX<#*1m_6pQ<0xlhJlB3cZ~I*Bt&^0P3 z(_uj$CCC6aD6skW8DrJJQ$7m5{j?gJ=2cgn84h>E%9L*Dd1YP9M>MOQw0p&r9&inO z`nMxz+D(OoU&MJaVIhL*#`B{q$xd#=jo7}=CwjtdJ@ZOeZn1U&`EggAhbJqCy+Wkk zwhU!Ika;T1gOsZNa4ORBqK$h@IuzjuVehPqQG_HJ{4_3VfToinQbZzY>6vd~D4)fg z2b^!&aD{+`@cYSUmb?1Sa}0|s0>Bob`DQp?2P(JvPXLUX$ZY?Sg zh=QT!vWM2UB`vfI;vx(fGX(G8_I{fC5E6RrdezfYbFPn9Lim+PyAO(d33znmN~`wc z9yg6;R5U(A5HYoqO=^JZ+vOhN%Rr8{2llq1=Ayu=;$6QfJi^A6Cy0>Jmh$`O3d3r# zo2JzfIn+T&&|ex_h?jFYtD*{M#uCyH9r6`7sqs!-K|8)r+HJ2;a6dUbY!51Sl18l0^s=H6v@GsaXRKE=ncj&FMM>IZJ?s$d-h zq!{ZCTpp-hC(O;XOsEH9mgxOXkmyG0kBt5i>P-1`C$h8+JM!Se=yd8$Ku_t*y2iYP ziPlD&BPEWgu_@0GrJQ%wWAgwF$%qc8$g))z6_>r3$9!8=i|nc{0aln_s}Eq6cdThB zu1|GI0)K$x@seQxL>@Go5Agx={d}>?F%uCANDvO0XRJ|_#p5vj`%&&_`<=uuHAr|k zd~9BjQYh(3os<+}7||kcM?G_QH_L|(#E_ZQ;ZemIyA!%MIb33iBsqm@b>!e^jHp+eioQ2 zKRAj{X{Ja95czi^nU#Q8K_p*^g0%e`1?K(jTiN71(BLjUsRA+Co0#i$Nwks9>g~>k z`AzcaeZs<-{3?7;w37?#vYR8_gCeYf@~QUX>7EthAFvMJ{CQnqR|*j-yZ-v5joZGOv@n|GOIdPUl61vm`i?ItH-52%R@o|0dd6)__`RB|0D18qqU?=|@W8;gY7s&2&k@SBtXkfM!2P0$(01Fd4 zKfkk!lc}LC9JFNEWQw-JzBuZi?Ry&WGnn^SLwbB~+DjS8Idm!=QQ0MF8Z~mP0BvKH zjo$j6?vXx|hMoNluqJV^!k0|@>CE@t*F@ZGc`PpO?D#n)MkCeOm2De7?vHu{ldKqc z&@T#-OfZfDrh-T=QVrzkQgnVpz>Ui1xyPbo6KOgVb=!Huj-87jdyGlqq+ES?{G(X< z@B(XF*fN5qMj_VJ!b?h9L6<_GK8g5nCbWLMK@-}cKv;5(v3)pts1ZFm^>*m6qed!i zq{0BHPKLA|W$+k}?g3u)aCBlS{NuDDXMIffm9kSj(BJ_$({?iXj8tMQz%&&nek(S% zGM~3IdMf-t>@}rV3{y5mVytHF?dfspoONQJf^$?n)Z~aea=^q=(h;V0gH_KkoRv&p z)~McsOJQa1ZU}Ol!1>6Sn4c_#oMWwE4G9UlVZ#!J?9@=tjWE#UoXg-4=!S(f;jws{1+}vtgX+-4Vz+lqOh-Sf-Jqdv1*z$K&F<B5Ox z!<9NpEJPc0mfsCmvKH$=HJM|PVbg?C%j<)jDmwf&XThRgOUUe)yk~TN#KN>*rXl){ z*t;PBCQ8S3LjM$I@>Zd>se!0`-j)bbsbvNG>>M$In- zCFR}n@}%G1|17r!P>E&-B+24g2KZJnvWA)a$`iR0hETzs#e zCou+3cdnOnfEWezh1Y`v7q{2DX!@8Mj{DFj7pWgcr)uJA1vU&Eto09r{W0J~G}wAR zT-d@ynL6)5^nZS@UAJ(obJ8fNAOFHk!{XL0k2RQv8L26+;9Yb;wVK~23-ZUhAr9q# zb(EH5WSNxdD^LFg^8r=A9H@)|?och`SDFWM-l%dZ1sucI&4-Ua!8~aB`&KmuxYCl_ z66*SvH0vfyQ*rpBkgM}G#xC+Qk~F2n?haM-4ZB@wC?Bq^T8Uj}M0nT!RyuWy%I3eY z`m~%zzJe=lP?zQTUe7~&e2x`UH~(Wfj?#5*4_fd0C$OxoWldc$hk6a7vEc+z-Z>## zT560G1W{9c}=S6T&LvphNfmc_CkE|`ny3aZ_FpuNxTXC4zKPhO_zwH#P4+x7^ojYdY%rgIa2u3rg;C zlzesx>Ik|DDu)SW@p)Y;P9?*C(jBSqa5UgbY3W407vOInBjZ33@{PDU0cHX24&3Pwf>Dh5R-OE*Io)Bg;!Gyeaq{jci(%uq;5&eX+F)X>H7 zf1R097<%c^elh*8!2DkU<3B^}KO4&uo+ibum!AK>DX^#1{l%aFaQxq1JW^%CYC{lp z^Vc21f>^JfMp_Ch%hsBF0`}S9s(fyu5&4sWD5+fRLE&k6g`ap&9)d7T(I>=VjF&m- zke(UX%3a$vi-bf?@%@&8ZH-(EI3^xGE?$&VflS78+}}A)sb;Y>o>G=`;&IT6dzKoN+Yd% zwn#l$f;)g6-o0a$hgFO}Lyk-D=}VnGbikoFzqj?W{XaFs(%0xW-akwo!ym@^R~n>I}2P>U}xq^%1oYzEzXKfM(PK1gp5Xu zUeMj4c9y*?UHYpuj}-E?GTS9e2fGv?;`OW~?8)Z+?}ZIYox`IvVw_xa(KqzLJ&;3_ z{bQgbv}K0QzjPbJnh$i?4cK$c(sG@&{nkKaLIQ^j98g z0Hrs6^o0#e!1-}|lQSemI@QSuaSVs!@^zdUN*(XS{-eBZ0I?=ck1ddPn@A{YzJ}7H zvgj)bF$nVh1DT`<>a1Qexpi7#jVbHe0zW*tbIbU-4PSj3iiD%bjs72CpcXsDl-qo^ z|DB-h%qgh@^xOcj9#A{aAVYW_#9tt#z+yl^_GQlpS6D!lAV7j)$PQoM9K%g+7s<`F zlNcOFG6@LaHWbm(5Uhm1g2VSwQq4@c!`T@PyXNS=Q%Xg4A__`ofU%To1fCJ^qk zeF~Yz2;H(z?_I-ZK;>($*bHG6&@b!sY5@?3E<2c7_LY>~6@3f?xdoHs&xa$=Cj@VE zMvVnxfCJ!~=lEaX!I*Wd`XAR8K`mfRNt&DfmXCl&5H`6LR=gjgZ09*v%x!kLkrv$^ z=1GuCd{9epM2(&1-QTc<+pS-alerakLzTb3c4D^u1~`7!z_M+rUg-B``_EN=-eKoo zk45{%jN8)<^HrMyValRWv1B}3{Q7A-Tf86B3y2ZQ=ss)%Uw`;0KlMcK=+*XfeV=&7 z=@HDhs!WI5x;qc{#cDjYU(wh(XY2Ti(ag1hD6oFZ+GK<=nfj%py4D|8a`De^S7UQW zTb(1aJ&D(3&4RPJ_lb63gLdR9CB#=7Ji!pmY&vE)HO$X6?y$QuX9)e4ShfefSwKr5 z8gRUv>_x+>({j-h-~`e@n_!&**K>5a(M0EGiUqL&NMg$Pw5wB}+R}26UAT5zIRfAE z@aDkUvh#Sa;wWx;-O~A<(6-gf&2E9{9J_%D9J_(*_#&Ul_!xdr&%k(TmRs+gXdk;a z>)D9eT_NwmkqtrexRm><17r7gwiR%*2lV*0*nh8DDD}|4c8TeQaPavfq-borY+M(q z^L5?7k{R<~eBKcJ*1G2&KT839&y!!U=er~D>udSYO?@|=a+Nt`#1a?GrepEx$p4uz8S(#@O;_mE467V$uX#W zsFwqpnOHui8#IBw++MW3Upx6>B=)LaU%t&Ztrd1w=WlV@lf3J_NnGi{ygMgq7}tOA zr||o%K~Z&oxM{SlGgCu_)`lX- zH*(!W_*jJfrOTlS`cT}81MX)2T)5bhG2o75NPNigG5kO4o;bkt!z*iWLqLoz`|!@InCi zWGqrKp{|chQU7C4+i@$jOTZASf4f!h`^SihQ>UKHWCF#;gTAj+heNS+dU>!gD@|vx zFtK}&hQsS$qW7I>UfN7KXE57L*0nlJ!IpU+p9ZhGpp%n9Sv2|kxs~wo!T7u3<+J6o z2#D*h?{nOnjT2*_;Y}%D-NV_aY4a+WmL{2gs;=R}Y2!4};KF#O8SaaB+m1(rEa;lN zuNo6p{)ZE3?a4FUCnu`l=l^DbchT+s)^)ef*~qnd6E8Z!F>{Hzal^=)xJPweM5-wfkP2OK z!2+d@-o{@l6V%&3d%uf*NCd}={uqm)NjAC@Y5EHa=vH~RZFyEqDB1T&DV3%eo4bNi z0Mjc|A`(wh0pOZ>H%ExW?dzKOpPGRKub~UFfE7`rG@Hjj=)C-E-JT_ClCTlsVqx^N z>FRqso6-H}ct%+ixUw1YS+m^-aibckOPsOAneyjDpz+0IT))Zt~EvIJevZ!vCX&^xq&s_XlKor|D-z#j8?M+}-uwZt=sO2&*X?&%L;qO6O1sVH#h2Gy9QptY3{91DiSMnuKMbC5&}y(Dl1wl=!_Qy*_rnJJE~xsbGN}*~L^-*A!2-36_fYkyJB*;*)NoWAZ{^&wqkr$m6Kt>YVNS>o3m^ zO6)zEs&=r6Fi5bt2YaCeYAKof6Hg~yR1=y6KFs&{6jNFRiu3-D8n;$<_l=^8^QqW4 zyy%KNTEj6Q0i@9|4hMU zsWqe_QQ5-sX=y#M1o0`!*q zL!n@Q^0y+lzw#W=fudLYDepos;^O~^bzS3>cK{9jyTy5_x&xBBc^f5qP9B4r-DFp3)f(Co87|76KV)st8TzP$eP zN}>1<=LPlp$8Cv0%CCG{0kyyo|NRZ7jNjlBp9=|u2ZUwfiVtRk}A+FgO3Jc z_Rl-m(0%1}Lg<40sMjd~z~qfCHQ+W;J&7Q|8P{TeV~Z|O_g=f+v_y43$!X&zXawf2 zqP6+gN{sW?jtDIT^=-{rw8E{9m&8V>CU2D0;`Zw-SUz6X`(IjxR-b$z>d z=`qZ2Jp*_4y^iJ^Mr_aA;|2*BzD# z+CDhO{^&CN7j(F0L9a0q$M}33>sjYA+E}Ag-`%`t`&#|m8FrWYuHrpr>p9gnxQX?(i4qU3 z@i{kO#c+GqYvfYw#e6!@_!|3yYK(80GIW3s;@lUgk`Q1iw)^(%g0W%-5nXXoCg?m^ zsr}K=_3mEYpJ>_ys){f)pLSiMLh>_)uEQaI%&{w*4y*ROeZ9x?%#o4aA0F|Ts@rXe z{f0w>*PDSDspc=+Zt+CmJX%N+Ey3~nn{2&M-dQ5XP;bB#nEyLF$G3A~DZntS(2>4& z@6u~f~`kCTmHICta73D zAKZnt?pc->d)_%!r$lw2JWFHW6~lY&H@ADt>-{!{=lbVg<#K(1KjayTcZm)(KgTrO zS1My(uQ%7IQT<7RO~KR1j1vv{M~Zo7R6lCI(}J@OhW@-$$j=|-BvKrZ8(ec_?;E5f z;{CB89ikt9Yfm-<`#gjDxWr!QB(e=p0=6HQRb2_xeo`Im!+JJsQnywI+T0rXAzot) z)l(_4KO$8$Loh9dtR8#&j)%5LSdP^=bFN6%A)&o z==$}4;_}x>CRw^O{^xZnP&*KKd?qY4KsZA<#x|2PXA=ruZ4))Msu8IDf;#Q;s9chU=!>3Z`la^^$D6;;?n{~@$5=a|1=dzOi3;i+yR$ro@w-*)mWY> zs#G63K(H_y_pw2*uHxUvX%0ul9(IqVw*|)gwsrE%u>%3PuvqFr@FY7h2!dv?Sf7I6 zQFek51$V$OShhj%6mZ@!a1==}$T zGf!~>+ByDAG8&o7{*koTpCNHCNGr{%F>#ya-T{YI=p(1(Y2zu_Cu7#VLc{FY-4swx zMx>z!_+^bPwlMP}+69v;K_INp6-cKF)S%lE06krl*<~-RtkGeQ?{D*jWz7bbrZQW3 zcZJK%W++8#N?jE)o5T>yx7ZF&{o!nq(0dGvHIyn^I6er*y0G+S%{1JavB}rX39ts| z6A|WWU+9%@)j{|uqiKDqQDhgGKhVdZgxK=B>rc5WS$~`dhA}O3i}4u7;e=&<^ZAB| zKx1tkx46yv8^*2w*Qc%m6JmmtNVCm?O0AKuPvkxLX&8(m1o?D`J3+1dVlsD3Cp9nBW@VOyU@h!fZm46u6;4UxZ z{0KRu72mp@q{@kwLcy04WOB%>l%!p}uF~szx9aVO5Ki$SglG{pywQNNxm&QPl#Dou z7}*E712?ZP*}i*7vV~-K%n78kwL@SJKCwEko0&Duk(*;8lPvU_RNt`^+_*=-`IsKkrE-L{}wr$n#Fyir~k7079Mj82@#ALy6>zfTMj4F&k0x-2S z7w1NSN^Pw3JZXnPrCJ2pz^CD9Hp^Lev;f-S1oe8J+-o5t@*eiuF78X#ZOqrnF(Bau zXPwO*;g5Mt0*8KK^A!K zH|7AzF1-ilErgm9Oo2X>$4|@$F%ss$VY#HB5#h!s<4IFV2$U``~ zayhNuzh?IwtpT7Fg_*s_z;7Ev9M9rYGG8%@Q_oWdD6(BN0zVI{S%bwhMKQYyW;N62 z*!PU=k2G0hWkw|)|Lxp>FQ4|P{Ka3U#o1Yef2F2Ru_r-~{mDb3r57PD7yy%zd|?zN z#2HMThM_2eYr($2{LSDaY@qnLOcZ4Z4xbng4+%927ycwLjHD3v(a%_&VB0vT1AP@S z+?v>XI(P^i9{qo*aVmPK*fU-^FTBS_0_ai*?Vnlr>-X*5-(!wg&o9T;Mpb9opkA$_)BgiXa$xGW_{^F=R_m1axF~p z_IBE_89*W=rG8IYna}RZ3Y`*aiu5UfV(!k&HSQN^?Mlqg_eS;_cthm5;s%S8g+%GH z=b6VS;T>rTdK_)eOD`R#Z&*t&Pk$B)3!%3`znDvAqD2m|wQZo&kV%FI@KS@L$|1xQ zvZ^IQLDU48eewhiy7A5UG%+nIWm#7DN8b$m3crPyYH=IGg;C3dK~Gv#`WWdaXH6;G zX7kD;?dPzinQpU;o$DxY!miErGbR=4(b1rKc@pDK$UIc`BRf_Q58>C62ybI{WLo)j`SQnJT0Vt#j6&o(kn#d znXr3~lsv*eTQ|TzJf*xrvbENvS#UUF5LyR&-3*UD9@~U;9{mwI{_M{UsFycF?J@4~ z;eph^LAr{q8H3Q-XG`-!Isz<&Jvn?pRCREfIdNK|s)uHgz*lV8@3YOvHpKP0dBf;d3k6euZ&E z(C2A;*Vk`2nmn?JnmkUQJp*Z?5$7|AGmSSn(?@8L-yc5=Nq8Hz0Ogqkg)8PTTP9VZ`Mp3X7Hot~h$z^~%oB6BW>+@8T9XM1jds-| zHbc;l>SJNUPf-xF&6P;Gu9FnnrI=A@$ex_!fe*qen0EIXeL}>o%92u9;zQ3+5Mwdk+7p$RcI-{;2jYz?kr=s|_yo0V9ibhy z&7B3N8hUw^U9=N_`?Zt%SyA8`nDZ@EjB7rz%R-p0G)5L`#23|*%cIiO`tM_GcE=O) z3g}is6F=6RP+i31v3??gW1~|85yWxS8 zMw10Qc8ck+pzwpqV~UNomJG!l^x$3<-BSfrN5Ri#w-%kdslmy23i|JW z0Scn$rF@yW#Ctj4-*_Df>I#ec+{1278=Sva0mfcAR!uY-GNdBku#Fb505}McVNt>v zmv3RQT^#ln$CC-9F{4Rk!oLq*w#vZ`k~kKdDFoMU%obLm#_Ij>89nR?z_GbfVK!`t zoQk~8>r|4jN9}~*XUs*6r&Gnjkp+AQNkbJ;%sG;4s5BBa=t>JJ`jKyOG{)Vysj68~ zQsj1y2K`Niq;i}^7`tG>egQl+om!dA;-bX^k&_3Cf42Fedn>B1#bF>L6@f=#+7_+t zpI24G_ddA*?W-L?cf<^S7V0sdv}@-E8iX*tqwA_PCU7a0L=Z%zVBsz0C=OlMNTRaI z9O?EguzD(&wk0wb-HeuFb#8E4VV;v3#vmBf8=LAk` z*9MylXojDY(i4-ylEVwh4}#gh6=bAZfK#)mL7~5J(Te8$cUcw{XjB_T(g>4&4^BK- z94GCKM_!KxbNI#hRm>uH(Gdu?quE$AtKPz~|U%kRwtnG**KI(6%rl2>3>^fqYQB$vmW~J~lZk^B0xalufe2`xLa$>c1q#8)0NQir_Jku-MXL zpn*!9Xo&ZQu?auY2L25@C^okg#NrRVWDMNT+W3eW!uqL);s}OiJ(VK-kW((2!dlf0 zJ&sy`O!DJlgh@@=DaUNelAhyLx6d-FQb0eV1n4V08FEP#aveZMZ4*D( ziY2&LkWo0O+dKbuICP<{zjG-aa(5;P)eI#+Ti>_%Y^IHlJ?VeG?HBwFDDUVI5}5DuN6o0ql7juTeHR&miBRTu2oiyn(<39foDo;DNaO`H=79~}Z1A)%}eGb^AD zc>*ptJR0hWV;`D!EuUvDbKL414sn0x?`#*Gi@ro}!U~jz&%;H%!5$gGKG5KVqw$yHeDm60odw zQBvaCM7@`*(e;V0#JiV{0IyX3Ni-(tJQ-)?obp6N{6>x7J-EVyHsm%f5oS4$i5(7X z$0$Y7P_ZGuP~=a4Q5}`mFvm4#66sZlw}nRdT{jRSl=O*!A_R&T{PYwFMQX7rLMnI9 zGsq^zgi6#I_F~`(w|}xa<$ok3t~e)L-5Yt4coe;BcD4;sWu?+EvxP(t7BRtdpupdv z64%j7vI`_1BYD~gwv%oB<<`agCl?7mVm*Pyl4eT?DGI7d|p$kfo?}MfI`A1sR+O+%1P>KBo0OL@zGo841S4nL}aYUL4rXQK7KQq7mOn2fz6== zU*g>)bK^Tcm0)GSH=$id_kHaW1>Fy~pYHyCYtG#CUYvUtoCQ=5e2bYKfEGdnhHgYv zhLYpxAdj^N7;k(ZiHgX%qLvPyelMR5*|a69d~nnJeEX#3I(ts?_f#fXanN__3uM=( zy!85{7&7Osn>S=uT?-P=SEl`NNDf1s zS)z)=C28A&{w#*_5sg#oxOD@}MevN-4uV&6xXT=4B~lVxn6xxv6MU6qe^#WR!9Qmg z*!rLrS&th+uvn>&IzZG*rO(^FN88g5MIPcYQ4x{V(SuFRuvPM-xQwsVR^xA{Ou>?x zpWQ(+g>-7adQ*HiRG~A=dTx6c6FhWN9eOWg6OA4FJPXf^UNn;z9tbwM3p7cno_UHU zOwo@Ynmok9KI=Bk?Av!(fDpq>!VG!X z*3LNm&)px*^|t6OqZSe1nmtGVhL4~Xw;{cgC@>FS-_?PN_ZrbfgXtKg1Fg~6zTel> zFfPd(j1e7uBF@EN|BRj^2*Q@Bnmf4&Z6L{otx{Il5$hC_0Xt9?wg+f+zV0~>5$uNG zbW)l-UZ5b(7MyQ~EOKLf&(O6KQLWaBlQwWM4E@E0g4{N{i?DpWGt~dbMd^>i)@YmE zZG!qSTYO-CJjack=`cb3Ppwcrd8VNKQCN`4D~~&p>eaQ?y@YcRKGy8$#B}f9VUslrSUezleasUI=pg`kNoH61dqSkxKN&M z@k;mf4Nk|CbRp+Z8u#mNw{$izn$})?4L*`DMpudkQ!qz@{<(pk0L#W~aD=r-%-C1o zt|m%pEV|rnR|redc!u5bbv5?;LRJmJQ9Xd)uAkO+AN-|Z&!0wO9BRscqR2>4_x_^W z;!E&zv*MOHC*TQXHSluuw1kd;q(Q|)LpEAtl9%orrx>~`aC#53J?Ob>p(=}Wjtpdk z?`iPlWM*gBsG;f#RiS;0(3KhW3LC8E4&3`~#P0w7XHJq#h#(8xp@{tn^;y8qACz$D zsG)>sfC0=)bozD$^`K!fD>SxRoW1UXgWc{Ze;b|MlCyfLWg*xO=OmfV$_UrU6FF_J zhC&lMLsOo$Cb#2i7DC07N;`wj(}^bnNhoNAE%K(}Ste~!sp8>>Fum&IDLn7eRf7ao zsvIN<4PtD0bw5~pSYwykr8E(sc8;(VRGwrq00uua%Vb2WL$c#% zi}dVcdRo#`>1#!XP?u*WQ|*y^X4o=X>9EqWV!qAgBsI?~R7@w`0(m}}c_2=<6wEzK zDl3?v3-g;fQ$m6Y%rT(OXp03J5rQ^sM`}t46#wDGL@_u!_YPimlIzM~c?En(&;(<* zlya9BLc%{ZRFY?EkMD>L zFHb5=tCh;mnOt3((iE*(nxepyUHY3d4~)?SF>)}UOZ9tV^PxToJo)#!wy;c6;GLr& zW{CP2oa&$$>2QT8Oscnt7RpHd0-FkBs7Uc2x6qDy6n~}vl<4bBUa35-RjdEiy^13% zx-<=Hz;Q0Q5~DM7-|li5=b#P7z z4VmkBMACybr1HXY7loGZ=goH~0Mv9#rHE@k9lm3-5!e&hRXLbdWMvy9gG~teqT(c+ z$)4#iD`Ra4aO(p~JL$^X4I*N~=KIlQQ^<(;lCzn$vOHXHNGn)Vj5rZb#Wil@v0fi+gr-jaBe)jCv+kO6L{gG5e_;sFZGb^vp=SAg6e)+3gA1YsHRw zA%u`<=V-F^h5)FPaUEQOK_^$f4ZEb)I@0MGo{#&D1tU_r!4l|el5B`>VZ%#4210CSh9ttqm=P%|B`sc^OoLKci4pU|YZAvuX0>FT z(Cl-RaJeZfwbLTSa(RUQ!YJC;5T+eP4`kF3o zpb#nrFIwxF`#qU}R}8Em4gB$t?x0`CAdu*3|SPR(amXLx<#z z=QJ$J(~WI2%1Fve-zvWiLyu9D_QPk%3>R%D?ViVoNYRUva+bv4mRuaV(wZ$?H2#sx zH`oL5?%_RKl4={=+9i?qXdFYV&NqhunQ~MT5N{{hdcE(r%d|SJU6L(}dLNfis8fe2 z-10F&-rot_-{0e~2_m%dI6LzS8Aav8NmOA*i#t;D3dzWu-m-3o)hf-?6U&f`EXQzi zVvb8U6{%-&C1XzjWxM;@xF1R9w)4k-WmTEg0wST$B-6<3mfh(Dsv4{Vw<3neGisOG z3V>2Zid2FJ)hetKplJTnQHZ_!jM?k(RKxHNthaUZs>>YNHc zL&e6gZX}-=bBzEbXMBYJXTK! zdy#mWleZmY3zmpt+J*1m8v;MI=Ce{eGs!qh)&=gQs%)Sl(A>ukokQKF$(SyOFdmiO z*bCr@%>wT3Uro(<$Ve%146;MCLfZwD5J?(L?QZ4t8n&+|!GVwn8HxH-vTUaiB5!Qo zgFDMZ*Axdp5p?%SF{eYh3gtDs6d$0G(`3DjPb=#raIS#M(KvpXBjEhoLH``^FDPQ` zxXhWjDD-}wb`&Zg;Y$4+>ZwWjP*wm%65JRnZMh0fKdBq&NLnBJOaKWr#Bdk=YXt>> z_wG0j&MnG-=zc;?hXR%ANO8pr*V2XiPH2LL!2u;yGEj08feH)bg6D#oGfh;Ld&ru3 zr;RBJIJEjw`uV9%A_vydLna(~Pc=l^(9Xy4i1g3#pMX-gJwY;k;i%z(-9a*7iN9C< zaCow5-t>HzKan<~EljbJkQfi-tf+Ah}2x38b2N&#Z8)e?$Fq&-~zRzx+HoLM>il zqP%fEOmq@3vqWk4fgHFbjeFgmgaZD2AZ?934WE)996ZeDldbXyLgaV+Eb;J@e&T{d>`6kk9202W>%Xu%&K~oo zUF~HP$7vCN+)vY`6l8If_8d%99DI(5k}gg7KV%Duj>}xWez|i!4xlBZttZA&H&s6EkM#v!A*Wl60GfYap$e6I;M(!}+}-^eJz*1eUW|KmegOzgK{<=8tcI^+R_Tl` z{_=cT^k;VPYNHGAF_ToopMd3^0SjlUeG+gOP#4k`sjxk}T*0+tB{YFt!ylIpx#Wm3 z>wT}rSb4;d4({!g#c8_#6e_pD_+ED(zg7JPKP96#CG^sYiRcQMcMP=INAGbd$tagw z&ETujm;=&)uvYyo1yI_gKfA!=9QY9}zcFZ0*&&abXP;e|^xDspRwfJ}$GRjLaREqP z(V#@iP4@!qO;RP{z&VuvQ2|k)36KgDlka8j^GIGiuUU)5dX0zG( zclG-jB_QhQvp4SM!l69GnJ`y2Wv!YtP22}1K-K%>s?!AyCOh93Jc_JgR8GdKn8@i| z99ERChv(z=yFE>;B?JUVL0?|S@C3nv>E*)hLynB?9p=JN&pyqM=s z=?Ef$yP4_YQ9~*_CPMpJ$SwMJ zn1O-VBz5Xd#Vbp!sy!sVp;7e&O5;^erTYi}L!lG`O0Vj8jX=r%eT)mu= z)?se&CgQuFQ0dRf)CPPSS1?O%*lJdLm6J3R5?#xVoXzM!c=P@KAe6RNl0Dv0fchWM zi1_OGr`4o3gXmE;q+!s*3sgsk*~ogNOQl%6B)xUaZMw@^d?yjYrIX#LOM(NxhBsWt zs2_uzKX|dX8_>Etm+|cH?17GU=#d)|)Jf8b^`Xk{Zg|p}!+rP!ESu8m3m5OM9Va#$ z&0!iYl^sH}Uz+q@Tp6JnRg!p7-c;q;FT(Lc+sV6}r9{ocXcR_L{oo&=pn4aQRC#F< z=lj9)(7|k41J`4K@vvK?s*R#_>2ppD8x(!6s`sN3BGJxT3hHc(+>H$)ja~Y(!fp)U zupZP+6#o}8(og}OWr%6NW?mfBxl|XSLuG#&zxg$G30e9u)`){Vpk%5`VK8#xk^lz*MRuIdP)|j0U@chsZVyZLl&?KOz1%xzfWc^P zUrO(`eRf2E`uqD{v+bQ2PJ9*)eu2|a!~39dmEI$4g0C+T=U-aQyfT{-CU^HA(z4M= z8h0GM12y>4A#}Ndm)HqR68{#kyF>t$uKx*J4NKlZ%qwoE9&_+&NgJ zVS|VhaUR+CDJ9uomtG(duG;XqcFy)DVxph&kk_&VOPsN1yu#ox8g1RNKI5Q~=EGM- zAu#|kX}PiNlO(qd6!pRNT>6izh(u`0U`&PTGTykQBP7*Qe=|79#)oT36GFY(q|?vZ zjf?T_CC#P5__Pk#?tABUA`r+KMXnU6+ne5h&fWJ>*9Th_?J(6z%&+sz; z$cZEV$892CQ-LDfAl{N&uPohMH>$yt@N*8|K5EZ%y^v6AVhT{)nR~Izq}tZw){&v( zulda7CWTzxbWM?I`Nq_8{})G~z$OZbB$14a^e^)QP+u#&Ca@w5Bxd!Tko{9>X4@^o z)ukO{<;XM6?5lKE%nL#;Oy* zaoBIV?>A__{!%M`Gssvkx_X&I$k6;5Fm_vDFS45(Y|!%oHz=?vTjC^=7Yq|%Nj*YM z!GOW88f_|1xnwHU?JZf?+piWeWjV#w2^`Og-}aNEJ@YvT`()XpB355n+BoA-9#Y%r zw1IkpF?~viI`%vXSUZhXCOHc*lXh0Nx^w>&xJ`_lls1}O;N@VT(xQfhp14H|Y@c(k zmLMG`p$cKBj)63}xg!jhfUoVGtR5@%!v{s0EbgQw#_gdz3>p^=|K^yqhahj8Pa?E_ zzE!J*J)RS2fw4BxsBwVzk;$)3j*uihY%3)Tq+Zw;4(#}Aj!j(#or@NV4!Tq*Fa`8D7BV0 zH{LvaqI4qf8asR16Ng;I2er_MvaRpXhv~Gitb>d99(qolZB@PrC^Qd0Z}Mu-(KPtCTTaBQ@T`PYaUt>MH}e-(XC`B;*Cw1FrMv$Q zBUd0fb997P6p;!BlPB4>mj@X?LG|Cly<6sgejvH#&Ob%9@9*{$Ej$ife8YAhsf2_1 zBoo+ZJgHYt;}*xf+lKUg_(Kik_WdYCeqd=25+#eC`wJ^JW%>Y~bG+W4{9YrLidd`CgDp z4R}IZK1R$~CehM(7*{m;3YwVFq0MOj$U+ckVqLXekhH*qh-hWs_cnqYcwnR#nGMZeY$4Wi&mMFm&V>&N+X=Z@xAcC=ZYBNcse;r+EQ)4&O3S9qTX-6AmaueJJ?~5?qW^k2TDInEGrW_HL$q z?X%;)4Ryx}6D&n(Yr}{cG?bY>1w6`00BuTQPW`|@*QyApr~BJ|E8}VGA9rXVnj5T- zOB)g^j?>I43Y1@-Jj9rj*+YWv$q4jOFpJ*1xYV|Q4rB~F8!1TTNX!YarxbvS}KJMtC!NnOd{E2M0cipVm< zxoa^(&z?eunqnWU0#;x+2CN}qEmiCdsa9VzVJsh$CEQ`iBznx;1@xhcRf90L7@=4a zQ+_|J9EF8u-U@DJp*?M~j0JO@+%>e-D=dUTeAQizBPWn6nm!J`lW*bk#! zbr-Q|Wu5Wq5w9330Ab{)R*3-#wTN<{oKeoeWW%Kq)OZ4`<7d5=TM>8+XlsY$Sj3QU z^L&!gLfprLp{AxL!9kT9+U1`_CV+ug<)v2_2eNU{e*>T*#pyiBB>yRzpj!m{ili{@0Q-8Ni`X&L2Y+%mz9zYSv~jpeHWD zxZV<P_>=;uri3ZKXb0a3%lFne37eGnvA4 zZAn$cl^j)`?cvrP6Z@bN(C`;a+pvXJcAD{K*x6i9`Vk$A>8{fsU~bSk%oo3JJMCfU&)e@DC@dd4;K` z24C#1h7%owbQ%KaJB{F6U||J&ez5x)`?bJ8Gb>?d zFr_jEJ_tu^#C>&VVuajKY}Fiw@mHov=Het7a1H{F$eXOGEW?z`2^mW8(?{jpM)!37OzTYX9gBNllI#W3WO)<>{s`x zGgY3xm7~YXINktv*MKj_+0htjt-lk&ZI|zw#ij$UZUsx@8|X<2KH?#=B4hQ5rO`Rt z@|OY%L5m$Q1LH8I;wG$(jV5MM$ZJygKMmO1l7!!m=KVUQ801WZ-1P$95w$k4A6Y4p0Vp%M@Q5Yu?Tl>QQC#`q%hl4k!EYYLRtU7`9gmdhJ5Yf#PbS8aaT6xe9H4yEs~x zl`@5rgjEY!i%lL26?B%o*5Pys%dd6>owTyIqb{c(sL9*0R5-+~IiO z4IR5?sWCMzrcM@G0VX4;E3;?bv9cu62b(}DvM(0x-?I?G#3O}m(YLprhbW3D2Dd?7 z83Ph4(DXm1wKsf|m3rEy4qNy;G%WXph@3j^eL7$D5*N=q-m)W^5-AI?&-_(VBVkfk zdV^-N`tmn4)VA~D>?#o5#3`?BxN8T2EPPE&JJ6!Y(Vg0kA^wKi?c_sGHK`4>^uaTy znv|up`bG;kenH2fF(-8^k-qSpu^!;CD(_3SkYexol8sW@Uy^6p!GMZ;zl&BoXSiJa zE(A*ctf5_b$H{a|;!Q4aL-BG_cyhx!pHIVRbJqQuf#^c~^rja|yM%G3ivUw#j4W1e zxJH*brSI5Pks5VFnvAt5*g2$1{2WbwBhspYek)I*D?+oB%3YgLMGC$7(Ui7HAuRI^ zdwd;s!L`mRX!_gd2~vALoNn;ga{`?oI(WLE=T_GHPwvD{KhN{z(W$U@Eh;Z0G}RAgP5rP??AKfLqJk$Q?JwBdVS}4!q(KEDV6@3Kd|dTREg$p1HHae z_L5C$lC|PV7HTex@`jw}q{qPwDLz)I2^qBO$YZ36c4Y)(52KBVgiVD@qK!N!K9p;S zmdrgHe-jl|K1KYT=+AP7Q)zCr<5PB7k)Y=mVE2~}>n<_@A7LNE;v!$)u4OMSUGHxv zHMkUcu&yWF#N~u9ztF0Ug|vHeodzGkUL&`)xT@P+5l?>b%t0QN7XYBMn(GZ$ zWq;$rBvQ`@19g06du%f1Ux0OxO-!^<+j)>%X zqQnzcDc_N3k0fMz_@sABvMC?Kfs>Ajyfa5S_mKiEn zsSX7nGJKAnLMwW17~}i=p{Z{_>NlKP^q~DZn1&=hxIU^=mWPUy_beqwI<&4t;p@rt zCaExiv43MP+1rQElOH%OdJqm!9kg9y_L>(qD^cpPdg*+nGB#td>k~NYlXh399b`3Mk-H%B~QVui8{TG*A;x_Y)6&Oq*7RsJ)6H<~(-| zEDL7s|BX7#YNbb;4%tNhNN>6+yGFs{2lfh)USltJ9H~*0LC;kVmZS8(SUl0WLu|~8 z=8iVoY)#B^boERNI9@hGm^qh+_ShX?VSNRPF$AbGaIENbb7)%J&8brH#%oM2fjkuE zy$o=C44UEnUvU38o+_ z+tN}$-a8n1&6OO@PIK0TRh1OC^A1uLI^MI9N|xmuHBtOID--%^S5JW`n+S^&La4s^ zZUDm=^ve|tsLE{(VNUB^T>oUg%!~Iw07*c$zY^e>)H6(cEDEnb`4pGkbDDJ-hQQ!$!=o^Mp1M_PpBBj-JHlXIpd1dkqx zO!TSTN1G>EYPcO0UOu7ze1saJnFX7p{*;R9mZGN*bwimyA*QUN-=tcYg>6`p87?d` zqcOfsMmdcCm47J~DJN3Pg5NA4LQ=pjA2-=;6Ynj*s}>SAI#}uFn%mQO>=p@pG}-2V zL6Ingy2E1kK;$;Z=5Yi5DcD%h9!&v(x?4Gm9XjL}3SyE}Yx+`@q7sRlj)L*lGS;Ic zVe}!xl4qqxh*zu3U$A{Y7bzn1E4J}@)8>2Lz~^B z!sY$%J|kJoDY!o-rgqFBx**KQQ~76q31SbYdIBR9&@rhGy)DLlV%{LMJ%_<(Hl$6$ zOIQw-_HN5W%ORz^V!Uj@UjFCdfxr-S;`F4Dw#H(*)({O)C2^sq4t12+52aos#M)2u z78f#l7_Tr&!A!Sc)(vhV*wcBCeYG(d^i>35!B14y0?~Frh=4>gj@G{p-vi@+BgDlw zB^p`d%rnn~dGU_q9hl53oDVN!^;Trv>VpXK^a_O#7D9b$j3s5zrU7W9aTNzwY5;UW zGe{XjN68BO!vt&hc6~O^a90DGGjy_pbu-gm!U&x(n*-g8PVDB2%{}*gBqwS_ZKvcY zbQ2DswnC1&cH82BvmSdIQ33{k$P;%H;oH95D@q@r!S$l}R5H{hy|@g&vWNji3n#1$ z**M*P(dCv-G6?86?nE1oafpu-LJ}oeYdo*9qUhr92M(ALIy@U*!jB#L7Kh0=LpJj<#vu1Y18QvXNc z?`z%{si~^71lXRMgVYOu_Giqm=0E)Q`Gf1(B-lEBR=5N6d#D%?HAv|bd92u$S(Fya z;^Hug z%I@5*0RFfsmzds!I~mpVD#hv43TJNE1ag4XcC;!Tfd*391}(mw{2UxvY3bS0`p7iK zkoA*TLQCz8b7%bKQkG6O17B5rrpTv>Z6a>AuU^q^-og1PghgyYi@naeM29B+v@B{X zCZKw=YUurcac7`n5|R_WTjE6n3JPcP7e8i*+6+Sb{t7)v#`bJQ-7D3lK)mHQdn}I$ zeGjBcaSym1leLU%E~hxjDG{{&Vnc#D#dgGrtm7@xb@@UocX@FlXN1yu&sH&h6%O9X z=-d&u^(tou`cQRnb#^*KK(Yb`QCj0xSW3r4(Uc5-(fi^06bt;p`y|sSk6$YNB2E}T z;{L{;Kj#%ClQRR_e8ois z`^niDgkCFH&FVrKuPPH`M`Z6#L%s=TVDQIN4q|~w4nd8^SmEQFd_OG)l}BVI7>nzF zj~p#|`hP78(c*3s<;L3z#3PSy@W{0FHu_|&Q6j{YW(;s(l=lAjW$ei^UA>WE@P9o! z*UTSovkoNfhBB&g^c>jG2Put3=I%u`v?iUHm;d56mEfwFYcvbI;{d^D`JTc6r*Cy> zBW7$YU>GOp&NIVDAZ|E5n*TpQHMYNh0zT}i5eNmtuPOW{GBuJuIwl-7P)EEpAYrFY zOb_+oofjN)8fRe`Ypj4<3aOoQK}2=*F;>#A+(xsUPrM%~a%X{54~jrR09NTN8qb0y zi2f^N8H_7=c?YaCA0?HBw}wW3P#HX_&RS_0z|`cp!Wv-7Ake}FD1QUTm9Soa>$`Hv zFUfvbT{qaC-m}F-SMhSR7cFR5zUCdsK5|pQ0qPx#nyE~s5f)$_!QXqaDoHA%q3>a+ zFK)3ibmZpBx<22!buK7TN}uD!{6DT)d@BRzZn?@Uup0HT94O8Ar2^q-m50@{aA+HR=ZzmVZ>{_TL6`EZ}W*A*mxDPDe^gQbdD zz1ZEU3ZWPI-^67&8ImU<2MzJ08-qEV2xV-xL+N5k6~oibmy{$9G=(D>#5+;E=SJDX zK^(B8eDGPRHo@Rfu{AF7g1BL0UQ)i5{$>j|rI)N0`e`?G=Ou;usBgJgQe|u4ObmHtX&{GX-B2gSWtpJ38`wn9m^w08w zpGp>REHxm%6ZS-Ec6c4(@5k1H1w#Ijg%_^+bk0I0!ia{z14dof^vuZ@tIw$kGM8QF zNaq!(=Jv3T;}sdkn55aIcR*ftT{vAgwOlhk^D$?$yx+VcDqIIg1%IBK{Yf+ zzOwDb3U5IDXfoWeWP)?;F1@sm0$w`QKO(~~SZq^JJ1_>+kca`H!oKoR#v$Jyt9=84 zFB}kT-vA_JE`y+=h2#$)Yv-DJ(v5+9)09^33e^_Y`~FNI;u9}j6$kE*MjII;5F=}t zI|az!&-cZXx0jKB^|JtF>3O{g1 zG0=rd4)h$3PK7JmZxeWSO=?=vEt(vq9g4(8@6-PsctH$5?fpn{9{ij%De{witFML?+)B2@%LI}>Q6(9qEri^nygH0mV`5V1Dh5-O)NDtT;fh>YL&Vag2*cVW z7KYu@*&@~Ma1(PY)YKZe6j2MeTkOlEx2Ot)N#A`!VxRAo~o#?^RxZ zLiixr9%f~K#0#n5QJ@?rQW^)U9W{(LylzQi(2|IgSfJkqr02MG= z-K@(&8i;areC`$uAPH*kj|I8kuZH-x@-8o0qlb2kHF8blieL+YRcN)4*2`0ZnvB(8 z6$D9toJ4F+JF8^NQxJ2E2emQn5X3uJTT^oVW|%cpbG?C{GDeoUm9m^9HG0iV@MAvK zWI~ty^Z63bbFiKh%=fW2jN3qXNk-wI-(iZ#TjBnI4e*d{wT+<)+6O-h}IR3DILfSQ_I9+agwhf;^uvCk|mbbBkCD;%8 zD753AUu6LSh!P7U5-gB~94d$S(QkU?a{ki=D|6W;z_StpBC?MAN3jQp?y`y08H6;5 zuGOu)@nNSCe$6WwdaY2+|ERV-xauyGkd zL<7(YM-N_Q9g^>;HWD<<$|!O3Hq2?qv7VieX4D4t$S4_mxZd54EsE{)2Vg}5n5fkt z)UuR)d&P1PfgfyG9(iLOxdAU3TH-$&*!d_Ds|&Q z=mG-d5aNximA34kOX0vJ#8$6=3OC_SptfBcV$I-u4?CGQuzQk~RUU8K}*ctvF9+HuZx=xTQzlkX} zwDB|WkF#duJtFG~~}$MyfZd!9okA zJUxSBvSgOE&C6rJ;x*2flF5w1jDwbaA{C5rCjW0%uY!@BJFYh*+muhCNDtXj>0&@* zcQOH=47;A~{?U-2@(Yfw;okfRGfqG%Hly`++N<89F;SL(B#q@x94A#fh1=_AHN{WC z2P^16%)S6Bb+!D#`{llDP_MC>e2V%5hZmvRdfA8>Fsr?YjlN*&m>t1wiYpuh9L_Tc z60rJYKGx``?PQ5RPQH%P!fM+K2&v+O5t{RNgX3_=F^CA)+?fn8xGr7>K@8Y9Q}#(h zNZW9v_FiItOf|wUQ`?X-`Hgl8%bR6L4g2 za1nu8E-UeYuX<*Kb4~b#0J#_Yb39`Df5j(NL=4KWwk9v&>?3fV! z2D^PYk*XQY5GB*cC#(Ccv)UU>z{lJUX!i-a#|D3l&R(<~hQDW-f$Oz@vBCb)#)JPr zmJODF1cHi+GE&&y;NHiPCT){68@zi}27b|`vcY&&N(iRz=o_rUu<-Z0`)JK6C9u^? zrl2(pK+Td}t!bzsAa&t~%RmwMdmo2+V#m7s_>syFE5G7J6q$}0n0Gik%av_*(q`vx zJZj{pN_o`;%a?OE3M$J`BQiAj0QL`o`G4PkiBz7^vWQqS#~yTLEg_srnTi@5V}p@K+318}PP_TbfZRJHucr8A)-IyCaKi)TgvntoWnmW2HB^SxZb$&R$9I0?PHz3g#PZNF6 zG$i$%FIA|^T3L+)u1F-MsDtzmlaPe~JLVAFfuZil8j0P4;}Azh1#l)z>_@8~QX{~7 zdD5@bagQUB(qTjpVE8!# zW$Jwi^cRj=q2!ANFv%C49}hKqLapH$X&ylT$+~MIyjy3IY@?fGZsPn8*p49Frb;Q2=|oc}Iox zaJZW@Ixr z=#0`f4fT$m7+j^9&Zs0}Q=Gjl;N8K>g3eL4zmdzkkh$^5Ntx&P341<&S8H4?kGFy? zAF_9t_l?PK2|Ae;+fvfHj*3FCYdFp^@1n6}Whmr3&w|HUIA%r|p0T@ZLM$FbS#c&| zPKiX&yjJY^P6=bNf$&|Mrb4#?EK&LKfRG%Tlkukc9kVwU^4*BA%2c;Y9{@M*ntv(B z^ve)cIQ+g3*l~h9{R(A&k6Ii)Qq37*tBVSb7XkbE&O=VXvVC@4ItWI%?P?~)*O16$ zYL{Q5*}T2epkJx0w5GRL4eUSgKT7qv9aVViVs zWM`(r4aS9A8Lyh6%N4YDA*;bVQ#zP~pBx3sOkP04DwdJ=cY{%XlEC-sac1)-@#q$v z(o4MCxmf%b?&1qU)>XG9h)H&EqCNO)^=!^1DiCvQ{AI6{9B?Woxoz5m|QK4_jdM{-6c zs#$MHsXo6Gu>|pd=et4dzboYuvPXOd2nPa7CLM1%`UdMQyJa=DvgI2ab>tVJQwL4@ z9}FO&!o@zkM#2jQP&l&xs6K*Ml>jv^NflifE}Ef}tt?YfvA4-mYHA&Sw|0DITpC`} z2K4tmfGK?VeKkdi^*zeuxG8-@=n@g~2PMc)mJ#V24Zxj$(za%x15Sxmh~MNO^>~3b`Jf*r8?~WF<|C&dhe=N^k{Bm^t;s=U)uaH|WP2N` z3KWcsOqy$xX|Gh0C<0cbFPybN&1$;?6Gtzj0O8FnSO`k>rC zS88a)^2yq#_V~0y0^B=l`!e|=hsHee6I0##fM*3zDum2&$8t0*Qeu5Bv#5?o7}| z7!kQ*>%Lpx5~%5VJ&S5Pyo-NMXz2Q`GMxs0HJ?lkoNoZv7lmjP`a+INiI;xt7rIp}EdT#ik08g?FgGJaMd((e2%{nY)^HMGqJW zmNVXSWQ(v%8iEV>9KgB_XS8L1!#~Y&A_RZJGpuAN+0|Szf>A~N;i3V|4s?8C zZ*0d+3iz_YSd35`fic^>*3F=;^KamK__=i}s|(Q#lRv&*I*2{e3;f$XFS?GR*<0BA zw1vPH!t*dnTz?u-__S;lVkIQd{~8y?e7W|-mFIoi3)%~CgM@4;ykQ$*I zxwFd9%DVp34BYk|KD&v3woHlbWf=pSvlJln7kiLF5M)|xk1TE#Xdh)C!agPee2pm64n4y6C`f=U@{z@XNs@KoB z%APao2&9R_gIHo8C?mB8fKW00&7mA;=tYgJW_NWNfRu~JZd*BUnhk?TO)E0 zDnGZXX8{XnR!?t#G%SY<|JU)!9dBP_Y}AAZ>TVO04sqd?4w1{YV4UY|2;#TuyiOAG zVbFEAGlp;T+ax0G!YaioACrNag{hOU`KXh3ZT(*JhktttWU^C%jQ_KSR&bftZ$MWM zSI2FN5hM49Trw3q%Y{f=@6p=>l~EZi%Lw)-n`^HDWGW+n_dUX1T46-2VM5lvREwq$ z=yX#10wF>1AQyJ0wr>~B95T-oGq}Tl5-fJ-rr_So(@vPG<8Of)Sl?c+EurFTRZ8>l z6Qn_7JdWq|c`(gw+w_8}z4zo0FWu_SZ9t={DGi`ROIVX85>w5{pN2l~P3RiAUZ!bd zv&}B!RsNZOgr*g;)`D<2IQ58tz{-}ncLG~#%GM`|E*ky*XH18`o;yu1`KbGRKMa)g zM2~T}z2v%;W}qtDuy=4Ty@9+DYr>1Dtb$7rS}gqfbqYY=8YV| zYeWVZzI@o*e47C8+N8U}RN)RF5B3=OL;*pbHSy_q7>{%O)U3YqmOfJu5Z`U#5vw%}cQK1t~`ZLvh zP`pfk65wfFkbs-)@S@e+Yhq1LsH=lrW4P+#3Zj11dRuJ zg>2pvxDucX-)_5{(h4)lVzEmA0EJ^)c|d!I5)KGtx`oiI$iTeG^XJY#qb?{n9C@K zaV5#LSx0*%3!X(vkqkH3!7UQM<6phO*d{``Kv@=VVRX^%I`q3(>S(d|0d3XCCJa)9SQ`$dtvsMK2k=7T7-<+x^&Zj3d{G#I`z_Np7Yw-nji&f`QujKHZSUEYRlge z(n6+BE%A^~0@MGR*Pt&un~_kiOZp&dGoG4Iq}Xc;V7o6BY#eKct;``m)I0>ypY5gw zSX+0OA=FYXQ~FBHAie^N&N)sJg^CAG&m<^g%vA_|4k{KI_@#eNfVBDX05ny9wZR$( zKku0Pn$@(>P?J>!W$KSBbSqJ4!wHWS9 z(oIlj*Q81zDgaMgjQnq(C14olY?vSvlJ}x(uKmjMpUcTwSAq?2-8t=mlo>D+hhZ+u z0)Scmn?x~SC~+i=+zozlFc*`5VyFOB;y9L*lvePCW=X%+vac{Ey82B6rOFB#tpEvy z{=p=n!GR=zk{zx$m;ggvEKzWtvhJ8;+h(LVxVo4Cz6LsNf@^{Xcq1_?LNlY5b8uf8 zY{NvCkc4n(2s)e`rIK50(Pm+T+sK?i0195~)TDhO`npx>r9A|KVDMXiX%zC{G$;V6 zX%A6|u`za)O4`$37PN9gwoQ7ox}02{3_DqNB@|i_Ng!_ zF(>R16A8=-f1$9F0G7u&tOGKDrv#>ss|>G#WDg?8nR^9W8?8pp3Ae|jQ1auzL8vyoB*tQTFB&4g^wAp z!fn&rNr>O-e4~PO>+z!uE(G2!4hKkQPMTQvHr0t<@)wO;58M)9928A58+6RbfYGv+ zMw2%0Y$btb1Jj9r3UtDV1xkHPWXdTSV9)RrO&N6sb?E&_3mXSQK#_J%{fc76nEmB} zl6VhuKEgKS1~|QE94!-G*=5FxEmOy?x3aQw<5*Mk4mDGX%B5qmK?u}JH6wPJj8q4j zI+!-W!0H!!URwT>1%}bF*v((ph-D2|;7$`}0NJ};Fgv<`1cb&eu$Pb`FPe6N>;ncj zaN*P69aGzG{}CCAU@|azU?KkKG0Co=xekE!t*Hb)W-0_BWDyj&!zt~Wjw1umQh?Yz z9Qq$(pG8(f8WZVt5AC-y>JrYmq=Vt;?N#nbqq%#OOlpp%#F1+{qjHjGJdo=zy+MgQ zR{qEVl{}qO`{tf8PgFz2TOCjgXt4cryTR*#ft^yxzj8-}@i7mq)(nzm@bQYT*_L)# zNz_f>o5SB6xtB0TYvDOlD>4)!mI_VY^o$~A77s^%vV=Q4E0WdG&^%VRziky@Qm|SH z6t^b8o25sQEjUChF0p}a>mHOfEX~ny56zPVF;65Rq7(A*oee@1b)^MYO_%|R;4#6^ zV!^jNvVs_&)UXH)0}?i5xFFduBq+#S{6k_)$bvP#Kq=+v)8w_f0L6Vv%jDXkO>H^` z-h`lk&zp+Um5JY1HR?Gqjn_I`^g2L;#4%tk4JoIfQYwN(Ii1JJt>G1p-qVjIq4bWv z>{GNjYd3*(ov_5pgx>66Eu#ZV!ifh(Nj3&{9S^~MNPZ`(-S#nl^E-*H4O;F z!E=JnSw*gYLjL=Tj(;PDJ#EN4N+-PM!i5_}!KOi&gskPAu@{MZYT|QPuc*$XqQpH4 z;Lca<#i^Y1wlqXMGn5d{-_0C*>iCdP5Qf<;yMkYx_p2cxUC$+mAt7!yDb^_d*dH}pmoC7 zSoA-Nb2qUh9x3{5hkBRXsg}TNu5w_%(*1UH;Rr4Pww_YiQE8G@M`bV2yPi@1cFkCj0b#7)lzD71Pi1P4P1W_&-SvMCoovP@P#vM zX#;0L3ut0fXL*MlBlO*1g1HBfb3hB_I@|pZ>J$)HxTb@M>9hkIyDGweQj^Q5bzk5V zSG?wf=Vk9FqkykZ#!L&NMsu?QvzmA=DfJnNZ>lK6M~UA72$0@pH3ttv20uSY6Ceo? zLVZl3i;mpHtEuE1JIX4->fI=mp81VBlK|bn6i23*7iUg%R3ld|&Webe5hV2n9*~yF zFb=SszYE^MNmT$L)n5mHYY((D!brV4|z@hbj^~h}L_|#9CJ4X6v z1F?M}tUKwCvzB#!N2BUx`A$t72ZY5?h^O3AO1Y=AlZ7OP{2T_-h{l_8s+8M-WY*Z zAEW6=)FJfmzB(VpSW}26B6olV3udO*DbLvP;iL>ZK(n^JC=2EhU&R>FhwIX$yfZ#= zI|6%r3Lh1JT_12tQ#qfVF=n^m{0%*jBn&bNF8U{}wi`m%B zC?RYqeEF`qSPQ}2C0)r4(f@&Nd9ld7Nby@!h2?aAsj13ml@H)Juo5cWx^SfjjgrYo zzhbtQo1T1VHk_?s)5Eyvq&&JJdcS1g31I=bJn&v!sR>bqPO{`4llB%#GD zm2t|%3|!ILkBsc_0+7Lshafn-tsHQ6=wmp4(dENWQXmBX*`=E>?xdpbUIsOQrMK0S z^^jVtIrg}2c@yB5%+Ua;cr3*hU@>h6bow^0G)1v&06@*)mT0%2n9yPNQZAAPIdbzO zNKO&4$nL`5qQ>0lNm}lniqzcMR`d`(br#JZ{H?e+5^hM(0aV zG*l7rzE>h6(?dM+YY^qh%~?<3*eL{m050Af0(R)CL{F_af~DQ2K%LHt}u(nJ^5;PS9U}$dtvP zJEssPRUgxj|N^Ui=B zdSuL?nxk^tBVZmEMC^$SY|$9V2j8y$;cXA=n4dw;bBE!MHR1|H1p}5&pG=xd zDhEBBtvvUIjSaZ_L2*QXR+0QrhH}QQyr8y)e-rcyc(fYtvVW;-4m8VRFfx&>KM1qJ z!eWCz-VVVP?nM*UMp%j^m~`Wm(!ay=Z4%sp6GWpZj;7v!r+A1fkH=q{{P+1BlHip0^0a$irMnFOLacX4Zm8Gz zthFXNfYx25=|=l=f0f^ePEUU^?yh{Z%;c%{VQL7w{Oo10%%1b_$5g?7{V~sq)`#o1ba7_M=ytO^0hMvvLVJj|< z9&RT(6p@dAN2&pQC+iJeSK#g<>YDr^vKnM%U~?8#{x=cNL&w;u6BV<3_nuk@JkmJt z82Rs6!G9ULu_OFiMu zFwln(zGu*+fSwpD-e|X_KK2Q@LU@Ef`+ub>;yUd`KrT)pnWM8JQ1+k;h_Asc0%%MU zH>eVSow92hkX#naHh}m?q#v2pfhJR0Cncx2Otx!sDf$otDh-05#EhFC`u_F|N8Td0 zlzRRueksxNb3Yh>8-JKsWJ&q4P|gs%yw%}Bl@LY~$(V0+@`RuiAz|pAyP7%ra=Fz; zT%pi-b5PXd(8vT{RNkCSk9Ek#IhECfXL|5|SMIu5mJr5-yXo7X;Q7eq zT9s~_NXUo#YV*HJdhM-J?vG@K;kdOf3SnDXs>MPQgwSxm>Q-8VoC42vp&yH7rE0v$ zpH}oi=R$G|^d|!f!;ifokjC{~?CHfVPj6eq4yC>Ri=)kK>_~*|L?QqH7(9yrfZPjz z$qUpAB^x5?MQJJNm(rp{$oWXOTkw?h*)g?Sv+_o6G?2oGIyPNH0Vx+e?M^l6?o(4j zB=S^wN*%?Ps8>7-48!e{g25FAyWFM~<@wB<9z8ry&tfIv&D2 zWz1Dqq2p>e>Nq71OGU>wMboLUXT^CnLbSn&1U(oKI(!*QTE`Pn{N5%wxG`4Byr^JY zM^_uNE#Ur%)=7NPmFtVu`|#6ZI`EO>=O@tO(7vJuVc=ROaCS6u0QV=b0R$8% zI-Z8!hm*T3^cb>I`FEK@8*U+gycR*mlbs}d_#T;ce%kdn*?SWYnJ!z#*^lU7=FSOA3Se7h*1#hp|ElADg*k z(bXw*+@-uyexDr#KWtT}^xO6%dIJa;BsLv?c?Q4FKTfbEfim(sA6rKII} zlYbg9XHk;=xkJ4CR<1feqFnwn;i2sl$%yh_2s(QB6-s!OY{{Z*B!e|f;YoC*v%LJG z(eP=@3QX;OIUL$uh4#BE`KNsvC@O~)HXYwEu-^{_$b;;FiTF@|(gVZ`+y#Q>^k1cl z`m=;*`<5(jGVjYv1`q>&qgniGJmmoDd#_9B2|S_l9UBPi7-Y_3+@+`Ou*gVSl^#m^ zO?4@K2q6p^19T-MAHKzdl=hGU6kcFR)Mg8V0N1Z#^#tNg=2!71K{hLD` z-bM$(F=mSEl!POtB_Pn()lW_N)^5pSH_$-+2POq;!l>bY-)m28<(C4l@~#g`cz}(gjgP7X4IhfgxeTYxUOrqu*%I7@w6DB>;uqGiUBFbyzuoMTh8>^ZVaWIJ z4Im(;a>=4WJG8w~aH>3_5u!~%rtKEsq2DuRLE%;H_wd2`&f+Yl5bZ_0!L8bu+Fem8 zl&?U4sa8?mp}=bOCEPx3mm>x|jB+YB6D?UZ5WMoIoJQmizX$3Qcmyvmu%FF(QvS50 zq3!k$MKll~qD_#YN*^nwr4L<^uY+#KGkOVy^>Uc2;BJ|lsQgPpuyr(T$>O0C5bXyj zZg;G6fauPm=(xb=^ZTqCd^lX#Y~75svxsSb#HZ~GFR*i}ykd6q_Y9E7SMVkBBQ^&4 zD=`6rw_1qA!v*i*WuhgE1r*7{S@K%a=cv$efMTu)9e^%>3G$W15GYeCTy0*vCmZS$Ea~3UPeA=;;= z=tjeKTizN1K7Wkdn7_;s1O8NUNg8E;Te8R^C9p<2rQ;NeN8-VQ#no<#X;XMGHCcb= z;p{)-ex7|u2)+RXKuVd@4`mwaV=|}jl(eZTOOMI$`FpTO;u~q&Zf#nhLSC^%vFN+Y@TP@MIVH9(J7Q6HnZB%bO zJVH1pULYQJltb{1uwPH4}z`QZe@Iq?JLg#U{M*#H9ks(E~Xf;;{r zDOkVU0nB4>=-cedC5!EU1eN$$J(ZrqSwGw$$2fcg2-pAuLK*qXr@tUdlt1$j++;t9599ptAHbH{oBSAsavd zD}(~~JgTLCFNu^U!2a~n-I7It7G`gE@v``f3ikU&rGlnJfHZ5Y1hTQ!6i*4!C!d)L zv%Co0kr+3C00JTeYgL@K+b!sXcC6DmaJMy4M0n*2ZI*|?!($4~&+UB;t~$ zls;Tngd*C}P6j1^k^->b5f{*O;}A^^l)a)T`Cc5{rSf5ju*!!)5$6wzl2p@^AC7gv z?ZKXue?RfGUnI`{8$iGV(UQeMhxKyPWNEiHYmI(W5NGCBLbR3diFjfZdJD3Ed%!m) z?F5`Zs7!T2$cc!(IKYu()f&bj2HG3;h$0%&X=l-}Nd3NlI;c*+Wq`$7R?vRWj0P|- zkZ3Ip1Y-NlRdDy}ZB(B6bGs+zhWszpAn~w~oJE8z;(xP&%80^K(i{?GeRUJdqD53o z?;1!x$klH7La=oTisj+%N;3f3CLVTBo&MauP0H-G?ElcJ4=zT@pG zba#B=?B6()WbyTeVC}l=hi?mtW%`j8Vd5(>ZT>Bgq9SSqps&j`q?gMCB41}!(3F2E z76`5)c`XEJ{_s@c_&rv5(T+LR4_|yBtWTQQQXyY|zEWZsWaHL1fB;|6xW2klaJTNF zA{qePKqJ56mFtkv^zzqWcKVMEgmtG9-Tf)yK;ch(d|3CEMFc8`KcC;>l=X7+17Y2e z!LsOH1SDRL42*~lex-b&p^^XmQdGnZ1{pnTZYX~P2vCi9O2+~QiN|!Mj+>iv0|@v6 z9GHA@f&aCJe^evrf^i$;U6Di?=nnbxvUbW2Y*jTf!HdDuhi0+aeJTMsYbZ@gQ^<&gQD!n_znNk42c1A|&p`A=`>ofU{$WQDZ*3 zk!}UJe|m95A}phqwZg4BRAv}mGQF&k5C^s*7W-_pw2erFeP}@@dd9c1SWYT15JMpO zY8s^$bT~GEfKirUe3lMDlOjVpD@bN(*05kWCQn=sq=)hKiL4mb-2JUuQJh7UbE}wkQAbM{sWfYdAPslnjxiC@BFJh?z$@#Tr^h2f5vk@4&XK;^9NR>ijm6qBHVb)c>b)Y-?{IU zG|VE|-lDKkxeA)<+E>mJ02rS zToVGas1`gW)O%ILLUxjv2(kmh0^Z6KTMBNp5t8mkV})=N2yiZ3XF%3e;jNrqf2H6? z3rcXGkqz#5Msa<6Vz_v$PL+R+1wTKRF-jRLl`mMg<9-uRBIIlfBbCdS3)jiDf4GS; z9k>DnSsL7Cn)-Gh_^XM^B{8P^aNUVuVuUBFj+YC5e(kwYQB2{n%R-+_E*;g9oyv#a zhliL`Xr5di8w-GEJBLP6)6EFw%X&mxGkbAWHAaoqCmJC^|tUV z%^&W8PLFdcP8LMre@k$eE#$)WM9dW0aX8xg?#=>5RV?`V#plZPbz~`NMSmIn!zXde zFt;nT#ZHg??KsQF1uUR>d{aX7Lx3}{4hQE#E+0;YBH9t+cxt}m-@|2$e^zwW@rUd5 zJBpE@#K;PtpWihz*A6uT9ZJ~^jT;%Q8@^^bIBe`TA>*EfBBiKu;U;%(wjrz z$X4ik6wwAT9T+LIuCvQopq&g2Kzjn|AO2&OafD1ZqTK+gTyHTFln6olBhA2C#dO*| z0lSZ@6&M8fv4V)Om4(haPKszdOfuJ7mVk0-T#q5JFA-R|-q6e+&VoXflL@%+s@xIB z?WQ2oiORo`H$bjXe*s}RJDcDQ{=-+a%eN5jMw!6X1-_zn?2hNsrn9xILM`*$?ad;Rlrg%WR#{_I{)j+KU-oAFEKb zM;=l(xIOSJj8uL|v@(xSv=Qw9w7nJ70rw*HF!1+Wf6Ns!9c0ag>!p{G^e5@y0cf)Z z#AB1TtF)xOf0F^+nGGPI#1uMy5LFqHa=M+Dk@O;^I##Z8mnpOp4v;C-`DV+ygfnxK zxb3p_;Gckb&&3!FCsdb9bDh8u;V`xhqj_a*3a+0;OzM1(1D_(V`&9S z)I+$hV&!@aaU427O4}{73_zSAvijAk1sV@8C96YIf3@bfIX6mB5~~5O^OFHRKffzr zlAef5+BIxCK4u8k&8|=f*BK7d-LHo;z|`<+;nAU_A?}Ck1gn-|E?$g6XU$l$Us`~G z(ZpBYfQ#qBO*g}Yr$W|x-4hzfB` z_u;1{gA&n1>(St6L7bVotH=v?S;Ox6|5M8Be2y)S7f4so$*l0w%jYv?U?C6iLg>^}BJJ%nd z&+lwF+WH8}PJN(px%}?-(bhi)K{Pe^fge{tHYK=q91B&>NDU`&lj%g|Yf3?h)kY7kh8Vy}|MOX4TH;FTA2%mX@=xD+{|o0y(Y8h;%}`Bj~^~AIn6vQ{5-0 z7i}M|zb8TikmdomFGx!abfj*uJjgg4GTJ5WW1W&tJP0Tec7QSlxM7x_;RT)0R^Q$3 z@BGG(f16O{UT0!t8$bXzvf)5Ue}9wf;UsL>MEmXi!zHN4b@g07d`vyy64#os2~X_o z_{mC08eG8)2IUB@=sE_QA`!sZcg2cWzuL{NsNX{ckkjM(8Plj7vg)+31=`=%j2+`i z2=lm_1*PD2yd}6RUgO~)B7;FWm>JoNh<3QYUpan=$G!1`5`uK1f=-poe+rN5J$yyG zK}tw^J3478EqK2tI)1uha5vHof+IJ=j1DeyK@g65RS@kz3RSLA0wTpIbWi-adhs!+ z+EC%xFuK7m>4N!j^@D9)p^)iEyQCS~hpVPgv^TKAGe@p=Cqe_zj_38m&CV{h2E5kC zOrS-C;<^b;XdZBbv%~2qf6#ci0WoT<7>Bd57RtFBNqxI_j8{g|4a-EdQI>!bC#R*| zsrI-&#$s^42JiO;$1?|6Mq+-we>O(_T}?rh=)aPvk-SbRK59?`jwIpepHN)A&b<&vJUi9`jfeNu zVL_f^vcs7nSYe78_4`MRu;v*~=+40`gAirj65QX1c%1E^SyugJ;YI5;_&^aB#hc83Bg1B`QdYR_gLXUB?#g21e9zH#Qk1$j?vR93WaP$Pt$} zzPEX*5beS16ytF9d)w45AATk*XCG&;5X+BTq0NQ^f2Htb0QVu|HPYRN#78nxH*sh) zR!j!gX?1@WeV*LAYk!saC@KtYuI$W92MYcioyNG;0`4N(B7q`#AVd+J0ntpoeF{d z&XKAX147@_x5rjHf%}_Wm6w+E0gA!h7!CaHpqLJP0|-!jHf=X|5lBeM_b}au%Ld)K z@C8>iKdzo_-T5^^KKEWI@zHetvKP(ecG21nb2?#^J5Q@f8CfOJ^`BC$YVAebnTVe)!$))gptnCo{0- zEjQ9W-X&d@ma|hjzJ{KXUOY_TPA#EL#wrg3VJRJ}#!AK$?_>bg_)yZTWkYl~3D&K_ ze^BfOvy4e;QR3H~>x)z4ItqexQm~$96xVmly&Z3SEv&obd)pDGV0~(r50{`~=3(G6 z9x@vrSHnE5St=?7>wc^TxIWuDQ@d~vER`}pP1R0Z@9xGX{!RvPcO%Ey(B0jOUbxT%ukA(BS5#J~Wwe|u;=l%<6XgYreJ^6&+@$vC`BB*KpG(o%}R z7HD@wI-$Ke#PyzONpse57Q`i;80?Z>*%l?HT2nzMLF~?t!NQ>YHDeK}7>7?<9NIrs zY7q{UK7rO;cp1sixMFU&5fO+?RulFkLQ~rX$R<3IfoUEuPpQhru&Qoe+27Z z_=1~?k+hFTl$bb;rFQWZYU9jcT!qK=a^m>#l}&wn!8Is{QfdlCk1|BkX{>}C%0lm~ z+v)aun=#=2?Dz;1tecD#?$%%#2!j;u@i$IHC*7Q%ik0iHP{#b$&MYlwH^0(JbbD_{ zmXh}52RtV)1bmh_cXSGuHebrRD6S*LXO$ zPYegx7e)OJlbLtISxb{6R^Pw4=cDyBaYOloYJdGzIJK zk?e|}Uq!%MdAEd6qUt4H7?cw@KfkUT8r}IdOfuIA;LQ9O1R@V_Y-TFof5wirxlvs3 zfP3xz!+8(IIGi6c-mvLj%ph(bWCqqfL$GdjB!l(o>X?3n^&(WzGEA8V^*pXSKB(W( z$Zq$-G^G%+RCJtyu$(hi##FzzcPBDG?az)cNEnoJR;rhZj*lHx#}N%~q(|26_>7e? zzr_FEZWZp#^>h@6wxTaSfAQmnJmS!}o+v26?Sf1Pt|74$5~>hYL#SM_YOH))@bgQ2 zZlq;{?)-GijkGpDu6~&K%2_jZ)TF!3J;E9>(0yEO06`X**`u)~U^&#z@Te*d5p>~`Pr4?5M*0JPK5 zhG@s8ENKN<5N)=Pw%&L9y*;v_yJxbL`H2f|qzAK%`H2ddVBN48ySFQps0=_`!G`W8 za3b^55`uM;5m&Tff2WY?N0g{Vs?E1hTsK{!ttU8serCrM+K?H=^%f5`zy5@E+5 zr3>L>h1)lPfLN&2TBp|RJh4-j^dZy{MRepMigwK93hh5~RUS_a5|2W(Wbrblet!*2 zt{XZD62Gtr^x|BXrP)j--!!0D3uF7kJjgtP;b}26LZY5fhRuwRch!EJ2 zUvgQw{yLyOfm5CS_ijY{B!Uv&jN4gUJ%nhd8Xeq-6ovmwCRPZf0*|fH!o{n!IbPjE zfc>f|z(yD|f2Z6ur$1S3_}4xJ9v;gt`CpP!%6m{j6P@FrfX37npG*UPIqmJgj1DM=jQNqavD!ZbzL1_vQ`d zw>YWR1`t50P{@zjkX~M}3CLoEP*C{SAyj$SD|Pyee**~XOvq90jBIlzNPHH6g*L`S zs=RxG65chnvp6Tj(@w>@l#U5RzRu&3^}h~rAkvcF00LyniA{#@*jJ`ifHHx z3cn(#s65s4@2o-leKTkLpEi>~mQncw=p%7W3XuPdI|r_!bSR=$ZbVy_J^3Xp3Be~1 zm}wIX5CiFMO5`K)LWwc@7xeNk3y5ex6D>*0e+m>ubTuj3h?h_)BvP=Zm`0}`3!oDJ z!gLOtrL?m+r~kC$l=bp%U{iTcgSwTsmKG%bOag3P^gu zA@K0dobV5kbSNT*yGE6yl=3W?OVS;~WAUr$l)+LdS?W7wT$~SP8Bc>#F_IQJH`1zY zRK&Q=FWb>Qj|9cPxceva2Nf9S4~nueL}JGrtCn3GKtK%PJys1V*Z>0JRcLaoe;QJ- z;CvD9im)k#s5+GGzEh1XU``rCBrd5Le@9)%xXo>Wk|%hZ5?MkEW}oTuDK9aE?gE@0 zuM{golYj*n0-OyXAQ56hPk^(vb}k4E*3=63ZvX)^Z*>3KONfs>1O|IPco^fh7kgI} z3o&lXkP_l&q7F*20R)twnCQ6ye*wX7 zD}{>V5v~iLq-I4=s;uspqbEjf2ya!Qu2ew z_F~)y5TGqYkAZI3q*#?Uur-FsAJl&chhr0{d>9)*z$}qqd=mpXYEm;E(a2aUplUgf z0)uVL{$(u*0U5Nh4ft3#E6}OdfavzHKyb9+^zapA&La1nz`eRkh&EJMvM4d--(q%2 z!@hIk)0k%KGV`6q!bgf?f7?Vgc3xf~h-I-^M9Zj;>zXEK(PO+UK6Ws_=!6Ge>pf7+}lvNy+|kbl5b@sA;)pl;=`fAHl6M4v=gR+z6F zMm6PC)||z4(+O=B(m!0KVPH^SRG6~cJ9kAacB^cMgaa_4KogV(m zCW`1Xz)TyW;?S;rf1{2YDE-4fgM5;B!NijIm)TU_w1h~SHFZk*ozawU$R*lC7G!-w zi6ile2Z#KHSt#LIS3%U-5Y38cBAO$ZzlVf$<~l_5SiEbbsECnSYxG-5sQ5Gu?U^=; z=z_4t3N?v-A)j`?B%abQE0pkZ;U$Y&s)T6OUAZ0+Co0cDe>9ww=i&u|&rD%O6sU;U zu6iDDw^E_g!XWVwjqJE7k@mEz!4q z*^)&OazYs%f7b`hlf@f0fB;#aQyPI5VE%dv6|vCBa9xG6M*LwZbbO7S9=_8O`Ca}* z`-c>L~Zwl6Pe>-2D5@+#kS7-f%;qVm}3232Ke~yt=)NdgsDqk62E^j!%KCa7N1eJGVa25-!gX`wX)b4iua2C@YNsxFu@E+b$pyFMET%o;j zsJppNlosBOzuv3e1us|@GXo{sTa?mqSEw}l*}(VkuJcIg6T*~*8$bYy#JO8SaOH0} ze_!$hb5b6n(0>0kUgfu%57#Z?mUk$}I9!r8M*pQy77tfk6fq(&{|>h=`B^SCrPa>q z;o)X@`PfJyb62m*Ukcc-PvDpQD3iK3K}C@N`e?}_?0Y5sW2TO4WQ^QE{f_cjzrc4U z1oL;+r{TXW58&3gPT~&{f{1QSBr@0We|hBj=Ozx;k0`X?xeaT?)$TivDS#?A+`+g@siseAKTcB~Oyv7kbF4L8F)H(2Sw`9>Pq}U!&T`$+Z zjfWp#CrJsjH=np)Z&?Zzaa(kwhbi*tR~eB1Sf`+Ja9~q;)ijZPm4s@-dO0D*f4#gL zi%Z&%T$QV=P{PMrE?L~>OS@Z@PrF-$5lMrrjVZL{&ymtIP*@QyqsP+FN?HY)MKroW zSZlJ3`maw2WE2!S{xu|AKlDS}3;iX(M8w&@UAbg&i?BwVoj6t=do)nLo4qJ6YHw}R zB-*8kWsyP%C%)BOKAd%|A0CsLf2YqyE6PV#8kw4@#Ea9GaF4~G*bYVfQhwq~OWJOh z(bw0X{@hS}ea!S$W%C;SOdvtx8mW2Qr5xIQh+KYmIjo3|lqwzP4jb6-11^$3YcXe0 z-2TM3GAMAjP7?V;QqTSqErI&*Xp-INW0(@$1jGs4uBerN%L*mD*0y9Zf1-iCWRKsu zS3K>^1`yD`Evz-90Q3K7$>PCbJxfz|@;u7rqxbQQWgq9VwD0|=NG z+smI=pNtQbegg>bbb8uef9T~Z3BtOuTe29Up8T*A7j9W^JX{>K7V+A)% zFW(SE1unv<=ftbAIg7AYOX5!jvxs(QCW~)F?e|!$lju?hTb=8De|T&;js5_iQXZxk zrwxZ|Xs>ol7GFOg@vT1Zy){()e=UN{3@h*h*cWZcx&Dr_;4HSfbA7NdKb++m`G3g< ziO)3Jk1UbO5`VB<{_jx#MKbw+x2|G_Bp%WJ#D9zS!!_P}`BHlO0}}7}II=jSI7h4`r?nIv^y9P{sTLLr3pzBe*?+dR>sI@sT}RAj(=r0Q#9Dw zv2t(Ncv3ONXXIw4P_z*r%S5EQ4#&de9;M?8Hf{H(39}BUWtc9x zu`35M4tH>_6Q*{57DS06Cqt4MSbt(mmKiY?{QOW*2iy!*u~9iXQaLFjokZ2);QC_m zncv%;wLwlBW2GFRYMoJB4?mRCMfFDI3Pf7ck3;Dsf3}WJE*1-Ze(1>6?u0x5?HI|j zioqQbsr>7GJVzaG=L^@%(~I_65UQNfZAyq%JRS#dFJ$+UI9N`GiLacSA6J8oa%Q12e-q)vW?LUyw$Hzp8fNLBZsi^#ma1H4u4`8)+UH8NbrROv%GdeB-GUDIjoe6c zlEqaLaZ`fZ^EBni&+o;gU=5kf0yEdwk)q=xFD>tCL$rS!z}>e%t5K;m1?$s5>G-RW z?jAj+&~XwnGfXnq3*u~hjfa;k49ZKB%=H*6e+3IkyiTWOnB>UMk6pRi-PpK7d!dmX z-=u;x^c`Q2DMYU?1098+2PPIDS1;Jm-44cPrix}l#weU=igdmuxJwxZ<(?9P^#c^I z>+HHScqT$5J@(f@#^JCAs9U*0^1Th?U7VoW)^P_Ts)>cl&kjT7peGFffub9^5c6@f? zk#6mTP$K^@E~wv6Qz!KCcBJTdj9Q@mf5%L%yFym3Ym+IoA))vCh(*bev!D*R6B_Ambrg1d5vMH#UAgY1snYrZ9>rqzF=KfQD=UGZP2^ z03-~E$fT38s4gEAfCFMQB1AMw94sOh69fXGh#U$A0^}%+LNN@2K!~F_s2ye60YOy> zxqWCR&*L;U9-+QP>qOZ;S!K|#e~yJ~P*#Ta(O^V<4=TU)C&Aq4Sh%;cGPDHaxu`Ed zlLHOZ_ket2f*q!0?qQ3d4{kpJ0$mtqBT!3=3bt=D^-0ZZ^gRdA|>*={)|WtplL7Inv6z!41qx4d!Xzn@2wQBSnh%V7ZOlTF3w~Y7}9x)-*=$azA#ez294~34#2anN)?gELu zn?cloJqOv*HbZ&0q()4pKg(`*4|Fu|jZTut8!VP`gs~+NfLq553k)b%q*eueIF`oz zvS=Qpb+{^Doi{rxE^IUOfA5RVPW}s{-XMw(T?3lbz~jz6ah->&=45UWp;Oa|k(R)D zuQw3MSkbL}mM6N?%)tk{)qPx`_ZxOFSFlC^EO$@@87tA`OBP0m0v3}g0SNSFW(9AWn&9MS!GSit55SP zPgP#6^WJN=8F0TJe@@oXerVFm5Ya2ASd3dU@pXhC6q+dukPl2rHfHqcYQ>qx_}Iam*Eny3E9T~OTTO|BcsOdsm7FyEi2$Wg`HBpoq3##1s+;@hvW0X@- zp=YeiSxf9BX`rBy1VomTWn@$$WM8vVg=NE8229S%P}0j|<8sSUfq2D-@u1 z>!w6}vm8s76=t|UUAR35xEc~pL;+6iPcSfU8-Yp~t>_rNjCev~faUf7ut6}?@zhBK zOPB-Me~NC%9Gq5)_KruC&dD}x#8;La+VBVusPb|c0emVzvDz~0(646i|1tblZ-qJR z9P156xk*zw(}nx6%`w!?IDdVVv^QIIczX*yM17+O=7%ajxvtKPP4x@f;?!?BX-!Jd zK|raCy4lj-Tg2Nfj-oJVRPR@Xj8;=>S?#Tkf2)@rk-`&v%BS*9^qLJ32Rf-8j>eIc zS@$`XEB^EMKaRP4HZ-R|FtU@EOo`!Osom%Hc8k>>DI8Ad&`j9)R@P%KrS~DVK)+Cu zQ@c8~M;8vxnkn@tn}NES*xtZ?r1;6mL zf9NVFdxLMGl!KC`)dKfCwx^y`^w4t~k4H)9Jj=!9Pn^L+zjvsZ{bhHT8u}@Jhm21n z{n8BlU;XRigfg5Ce^YoGsLFGFI~1ZK^gdrQ@{xt9vxBG{8nlofx;VkuVk;V1^~|d z@Tr4jhrR7nmvJDEDym?gKzn=q3+67@nbFy!H6g|dsxM4c3@q}g=J_*;O#=TW_S?`4 zUf-==*ldTCu58<0@JK4P5NWw+Dxzmp>Y{T&j{#WYXeEHn#gUmc*9xELz=U9S4mj zRT+Q#`X$B>lK&vN$sh~~A3NT%FZmC+o=3E0oA$>mE<*457Nev+Ur^$5Q| zZy5~c2I+J|G?)RqUb=9|F7CSGfsK~=Mhl4D-3i{ZBHIc7WC`t-nh7kkr4N3aEF%6G zM`9+~pEHF~$psToRNW#D%b@%Is;T1r0+Jo;XC%^gODmFKkPxt{)5NAv*6bO0fqXhEFB$8|4& z_phAtT*d#<4VI zF%byFp0e40E)6Mh91L6h7zLHzx1Wp;+Yse zq@}wuFJ%Isj=b?5H87->X+@zK1S0RBh;|E(kmPfD$P-zvUb3uRvOn!dQzLPSdK%M| z_K^Ix`23Rve^MmT5Roq+sxAN)VItS@vykF2Xu$-e{@k@WH0w{)9AVMMEiyQ7hlqa`+9dzaFAf}&`{B%~+PDByB@k-0c;`R{V-*}5CiU&2`oF%g!glV*7 zQor#Ce{CUTl7ttbFIK~(gM=u)0izxb735RK6`R4b#IIh0J_U$eh#qHqO_AlZ%Qfem zD&MS*o$<=O&cgL21*745&n$i7R>dF&ulw-!11tX>NbLJY%wQ*vrA$zAN^6b!l?-a^ z05A#qCpD7{=M2iA$UXh))6F;vxUw`kpmN}&2d-=pIIA?hW(-sM3t8#pFN4m4@+CxPuCP2j zU;)K6jyUKzd8|py=KfAHlIy^bMI8<*1oQr$YN?9pQzAyWJ&NXkC&)BWz`zXnd7X%z zeYNL6_uQ|B!*{if2kJbEb+T178EugMdZixKF5L%y%P8PCfHnA zO)V=KNSI)V7lyP}*hGgLf0DSY&anERs64AH0a-9$UE{4FARK0uyzlABtn8`zh9vrf zc!#kDgeq^Lgq8Y-PzI1M&GRdaa)F5yenw4=14R36ou`6vaD2Cw9m!(jB-pUFe^2p@ z*sV~^xXM6fO!`$n9#rI9ZZvyVSMac?sO48JIB$e5B&yJF5D=2VcnA@|B8lY3jv3$wK{alEQ9h!lBNi;#l8&Pf>nVJTwt1L0Jo?F_&C9& zj$lj&#G|ZRz(hU)F?(L%F>ffke;OBdvaXME3X@uRDPxz&A`hA&cMiO9?(Pd9WakT6 zj?i*Wf1B!j=-Xz&*@Po7eQ*e2XvGz zLK^Lzt6TqWPh{<>WrKGm9_iu>(*a9znAfP#5dl3C@dPE?@9BtB7BK`8e`ApQB&W#t zDD;z*nvS%X;{LoPco|biP^9dDwfCo*5fA5|Q^ogJS=o>rYJt5@P^^Qk4$;v{z!Y_j zB!g=+loVV((*n``<r5G965sI)5B%>-zHAe~>{JC|;S1BP*Gd*_L++aD-`c59*sA9B6R;rjA z=rIYvFzA4cOm1oAf1YQbj@)3fcWxFud;f&QJS`=Fa9L$hV&fi>~puNe^B^${Uvaw^dSCv@{6mG zoD6(89n;Q(vA;i<7L~8R$h&L9Jgzez@ecPB25>d9Ghp_oZMM4&H7ane>m_gCkT zf*`=04HCc90v+cZgIaE~w9H|gH`y2mFQMjWn$yF25CWvPNTyY7!`#Wr3%m9E_PD3O zHFyXx;|+^pf0()QQ-Z^Ux4oqo`Xk29X7%#xCsNEN(ijbz;Ygp@D-7PAQj0=k*H_=c92#sxkYTZkxF|v1J>EyJPx`+r4YO)bf{`6O`yt zylPS@6@PKR2&>~_MUE;tY9fqH8W^v#028(C`X}#JJ#txt@k64K3px2s+5}3Fvgn+P zDYahof1mIy@oUNEC5KczOQfQ+Prxa04E$7d?pTc0?j^O_&z1gp6#X0_=nWY$G%9|x z{aE|~xZiF1DC)u&N7|2MU{ON3%`YBb&^9>Ev}}H(ozTuX{YhxdJ%y6JK#;*wx{}x{ zd!pMy3w0wgAU*(t2%FEdNm1F5(x@`ZotlQ6e=ftdPvc%W6RsmxM~7Vo@ZNS)YJZYT zg952Ho0+AzHA0rZ0%1{yznb>c$?X8FWyGrkv++-2g-%?bC<8!S{%lgbbkhm`S`g0D zlx>IYX?fB2ZeKoW`d5Oj3-kl12deBJA#=Fmq+CA*stQbK{r92E|YIoh8@`1{{}P8Z%gT;aBsj$ zQ&@WfM2f{ekX~()4KB$|LSo?C5uorEfAL8>$l$fuz14n?mV5ESdGGQzob_lcJo$VC~rsx~W7PgjVgC?_dPg4nbKz`mXZW;%LDxCxWyBlj=HfEO6$kx=}AB>>Le{xiA zm7{{zn}Veh%@el8s0gE|K#i$cb4!%GrukxQWpvuW1sk}Y?P+zx%_v+!U zUn$fypaVHXvM9pK%fKOA;mJQz?M`GfzLlA!!??AB<9)4LUHj5C*p5ZK9m96-gzsXy ziO2~lxy*Rz6Wt^RC|HBk3N2Fme~$dvyA@PC$)er9H_L%%?nRY4<8MqCvj?`Xr+v*m zee>V>xI;Ysz59)bMmgf@o>$JZ!6^<^AJLO!!53Yui^KozM?Ko^tNGnLy%I0+K`ryS zb9RV^297>#N6zMO6phH)<&jehQ;K5G`39{!L(LHSAR8e(g3C^To7}<|f8;jfo4?>S zsA(i&Yf~B%?x4MB8%+{+AeG19>ac0zWW_v%D1;mGtC6SS#g;l~A`S4W9RytY>OdxI zb0MUK{}30@aC|Pmt!r><97ECdeufNPf1mg9u$4@+96hi@eZZLhRMKD1l#iR?(7st_rauq>8zX8e z?KvERD_|pMQ~aE;_dbXKm(MKoJ$1y7|CSfHcNG;!u58Xh)*LY9%H>|qVNi(h!(#9e ztq*Q)Libf6LzGfYPS!S;Po_ zFPCyalzb`MFSN=MIq8dszDXCD8A7|7c(19w9>;-Y%LFhz1l^LswcnyRHRUVg-NeLFQtWejf-ub@q2r)Mu4IatZi#1z5=7Dm?%ERvre|zI%H}BH*90G zZ@cUml;C%}7Kg$}f2V0cXjljrz12fKrHbb1kN%?*Ylz%USl1)7d9vzXq z{bSRkNaSg1Wbx-0l$qpR5Yvn0MX(zSic+sC3+fq64iaMYf2g9nK%;9Ys-QiB6Q=x* z_)oSv;v|*bY4r8+(TDA^(3%f0`n2ocQX~?1%N{;c z1eruQz-9_ju6&x_ZOCfvxFxT?9p)8{i42W%G&Yf_gU>ia7#UjQWz^^xYMDtjPvRiQ zVY$qJ!L&oqK#8lpq1%9Xs8`{4-cRF++84sZq&ji{D!{xK3fV{_G-pz#9vr-vjC~UL zdlZ6=f88Vb%%lu=b%2C^;(I1V;jxEe@X;cMkP32zh`zU$Ny+p;fb(Y7#zrJFhTzD> zNi$^O@*C1WlWN`LkIqaK!&}hv6F^^j2(>0uX~1Ao(mN10VhdczN(f&l2Ti&^!hcx* zM-7_^jnzgsz|IW-4(kAUeXBY~fN@awHqP@=e*)i57tv}bM}>lkgM(%CgrBvfBH6H6 zN(t(tCY@-h_`#)E?ti+;W6-lcpfZ{tar{$& zf2RFDg@TMjDoZmfONVVqWm(xE9@BiE)L(xaWb>agyzf&Ru)N&WzzC1yt_Sp>0)v)U!t=Pcn=^2xdVa@ZYARs>;<(x4|xs}l! zZtAwuHw;x`PozrG$S6E2`dT2lO40gae={*&&3t7rWY;q^4S=)~=%bE>v}RxknpX|l zsv0rRRx)U97wVfdlniQSIH(_dr}uLhcZH;t18u`!ofdl=Z;v9LNo8sYV4+G)qJ97i19>eKMdsM4p#u^h<*QU>iM7fTan{q_g+V zEXTfr1W*MLXuPBgf(t_~g{GOF^&xUk{id|`8X^ua%H2N?6)gyG5qeLf(FjS(QFW_pU0c( zX*D4W-4hO0I>TZH{_}{BOjIID$pl9%{DnFFl{u@O3D4OO+;4mBOcH7v`@=DS)&{B6 z5)w8wy@MkfQ$7`PNyUyxf8+%;u0H9R@<}f=VSIubsG;6rT8^Z=$PjkOnD+v;(eFZS z*ZM;cv!OCZzl2Gd+uB}nj4)Dor4U+vy}bgUVMC7?xH@&c5$j1?XjGZ;vdXvA%IMD)+*#`uOEg&OL0Ju})rXoQepSAC}tvWGQ2l(h%e~5dr@wD%-vx-QQ zG$g60SuvTJ)3X);>ZnncRv$%BH61Ua^f*_76_zt7KXst`;!g6ti!`KgpdGSbgAbo& z{Z5(y9Iajt4el_~-mCd=T{*@qD|Zy@y%P@&~hfQN|O z$K5G=Vv)EH1rNqMiGIXBjVV(L5|jNGnw7Hb4d8Wm7=r7HJ zpiTWlc)Vx9z=g+HO@HutM}M~6#9MB{YP$->)u&xZiAu0xR@cX8dvuY#M+E`HjJk$o z1#Qktp_nMy^-h5E(OHeC5nWN(>6*1FP3{6LaG-W}%aJH10-M%v8>@pwBiZ*U)8?b0 z0rXe>>kfzHl~#nhM0-k@{q|_2e{yOsj!8xsS)Zw2k|In?0e@tm($QcZlV&4#nUM`j z@Pj$BiaBBeug0#&PTunq+qC3LO_qUVj6AX{CoVPy9X?I-QX^6ADtUnY%25Ymo2mwW zM8s(%()LAa()b<1=LvxCa?S?H@fDbL8zs8_SVAzt6W{q`00yp{V&+jjdXHBO$^ke` z5YkmSJ`1b~41WksfnPL6SdyzY%}z(jcuq9xaXbHz4o)B(-7%_Uc#x?A6b}YsEk_#J zm?Wa90su%<6rUS(%$wC0l{me+7b1NO*oBn-)e zz9J^#O@Do9Ts@x>OMhx^xrhsC5G2eW1GJDFnf=!ye}BC&m0!wGwlU3-PWfDvhFzdc zztAZLWivaY6Qi)ZVqI9fcCKWY&(}l-cZq8&LLawaV3`Ja-OjYqn5cw!nZi=b;(2Hp z)K)mLWtx3LngZyt{4?lsZTgj`$EjGP#~;K2)_+AZ2Q2Qn;W{gd_9)?q>>8ui5j*^o zZd?-LTytF(xGk<&+YWyx=wLD^aSy=`)r&|VxIldBGmkN!@@oINnH*H(f2SyN=YtpD zCZAA|NApeP4Q|QF?+hYzPX?E+sI3W+A}fNv&?ra_3J#7fY!_c0^o`Db!Of&YXl)&a zJAXmnx()8bP@!e7=}PvkoB2|hl>2N01o-wt>2{ihfw$Oh!y;_jZCY^BTk9z!x$ULo4>}b0TtVoywDDH!)MB zIa3XUx)m(Qh5UQf2-}oN@*gMhy%*|5zAR`iuHgLTvUgEn5*(= zPoEuSgbjKRP=gKnqrX(8lUi1cQt*_E0uToIG-LLH;4 z$V}kq)AsSl0UR!oGih^C+CSwn6R-*~SnS$S(GxV_jdV;L5J_W9)P?;>&VOC~99lwM z3y&P1gG)P4D-|hh2kXVgXUW`i{2WMh#O`79NDo`hT_8;kKK=}nRJOTkiU4Ey;`jj` zi8#;v=;Yu{d)ICT&nDu?1rpvAqZYrqi%$-jIeuYPjuPWG^5+y7anw#F$I!W64S~^J ztaow`)Qy~XungOf<5eO~Uw;vBa;YH^!RQZz@-tIG;RxQN+H*%?N}7hU4j5az37c{$ z5G4%BD^8)qDh2Zgl!0}t4i(I8Y3=`LNOUN;f(s7@Rq){*G)1}=2TUdp0lfHVB_|r) znM6A9Wpd=TSV&i5CeC_o6+8MfenmP*z_s7!+w&Z?k8~A|lGzicIDg{d?!u0^lx(&~ z(iN#<>e|by@P0;q981D6yX4Lwp^e;opP0dEjA!ALSPmxiN{>_dtfx;mCuG`B9P?3B z6@)Ff7Dn6mMMs6W+2vHQRaMA?xapUq!tWQ@+nV(%jbU=}!u5p0S%_P#$^MEgRzpSE zBXi+~(XxPe4DO%sOcFe%PPjw&hcz6W5#ODn*c|&< zy!kjx{Y5}voNSKy>D@a70x~3CUg5Nq?Fq!AW1aB+)0|oUsD} z-!YpOV4~uY5_t5pEigDI!6R#Ui*&+sy9yo%dF|yt9Pd|U1uQl{|9QZP?57=@7>Ae**Ranl1{WChf*0=q4OzIjG$qghz!9gaa1J5Qx2b>TbR;gVZ zPt)<+w2Gu# z{zI>srR74OZ6+!j+g!w-mpf<~Dn@4gReEHxb854iXuNr1`@jSR`kmBtYf14946kzV zdpi$dUKfgxI=^I<&@k`&3!tiOVDIm53+A+_gK?8PhV+OM$w_fIvJ)l-BDg$Hs z=Np5*R)1`9e9Cm>9o=didkh+88BhKkM;H~wLlH*%ty*MG_JBpF0#Ft)R<&T1z4g^p zX-A~8e~Qk<2{-#^hJpq_D@;?V!x-fftL!}fR?pT$2T6tR^Iz_7^yKxEP*UJhjyOKA zf<)#;4G-Pl2Dy-e%s=*0O7@wTOhVNx$Vr^Vf`81S@`EGDA8_<>C*dQk6`V!b(uHQm zz$0SgnA zmDw{*VI7Tz5&74YjMyfRMQ^su?sIy=$O$n%BH9~3n?WB5BbXglbrS#ZGIbcKii7od zNqeOLXr&Zhgb?0- zM+Z;5+O{b93Gs%Q7diNJ=o;+2thAwG>wnAENxY6-@%|y=(M`bA(D1xNwJ7j=o5+7F zK3F@41*`-N#w~)xCIkqBdYldUC&b|RaY}F3<`g1nqaiJ3jlt2JRacj4 zg-GDCor=+ZjScM+NUuT3H;5Kff&T5TF5qO)^>JIlgx$pLgCG^KQ>$RQFi4~csecqr zR#N)E^AwAXIZ27pf zjO7VEnSF3Vkd#~IMhTXslU78L7U)=#WJ6(qbx&GmfCQ3iI=MPv%sqmk5eLeM+bEO? zi0;X%>CSDN4RJ8``QJ6^9M*B?4u1-+v>ODCH~0=r;A5Z?3LY96rNP%QetC%18*EQl zHaMVkEwqq%tGE8l<%Q6(Zv_qRN@q!7I$m$^jl-QDfjm19I`aCkfbl#D?&=a5es`7B z$Kdhfm0u0i(D7$oZNuy1bOa_|uJ%<|-^S}Z{X_(MM{#RpF`)yEN37dR=znYND?kU! zy44tO*`~F3R_yrDG5*&gT2bk&>DZuF*>GW-GgOl}l81m#(2|pfX2%E!+$s(sc?-p%b zcCi#r0nSBp{E=*_G?V0j>%VAIEs{uIP8CIti^$)9{<-%uMG+S$fT1X4a2?)lY3ORK z;O8)rOG9m=v-3TW_r1r1Xq5uXf+#PL|Bid}wC0M@IBHh<0ro6~Ab;Pm6TJj5iahf= zz69g|oA99761dPr2|qqWt|FYJY(TDWLOGq_bNuXhkJwj%oOK(E0(;ZOZmWd0!AGPK zhEp7`T-Dp*vJAnQ+!*<>le?cqOu_g`!wJcr7b zG*;;0Zy5)o#Z(JGgBO=-f{$8!HEMD(B(hIk&YH8XFeA3FM)`SlG1W_zR~HfD!Vq%M zbv|wBcBS*u%bKy@P&>7e2ur3KI-ZC!%zzG?Tj{wr3Z@QCTYo1$60pqjDEb=^VSm1f zFymo2%02n%W@lT?mx|+4n`0+hb>Ctl_K>$BwYfu^@%Z&yr*VATIui`zzN#d077Sc2 z)K>v%;BI+-uez@quaC)GqC+$S^nlAFzMn12kl?>={0qmgPlMjLj>GX}i<35h|BPWn zFChUTevSO^W`9iJZKeJMVviW8JRylY?(RB1wx=GcId@C6CW2UCqL3U1U%FshOPJdk zFv*<8-$+zho1TbMJzIuJbYUiP_E$>w41<>&T@;uPCOc=`dD9ZOh6$6U_BU%=-a~+i zvtc4yNNv;xe1Dy~4*3!VY7qk8QL}h`MUjmhk~4Y;c7MZ>M{IRVHD4}5(m~&Jl9h)C z>?5_dpbNUC5z?{gAIC=!0lu|(3%=S$+UO`6-MP={>w-j}3PS7M5%qYbk6y7#t12&R zy!{em#2&RbIKfL-acB9iq=+munUC85;X}=%ip$XDgJ}`+NC{Nu4_gR{ z#duMbU4IO%)$UD8#H+;xnd~m#(b}{WTNdq#$xdurt>nxm9{az%@UI z9~49}C|8_n%O?;d4S$Umdtv;EfnO}}FD4s)zvj2ssCqJ^MlRWlb9J3@H8?cEetT)< zG_)5lNrdhMxi;7fd9{}ehd}dDuU{8iD~qW4S$~tv?dQ<=7;KZwu`nxfIheK9Q?KYd z4UCPDmqq?7j>y|tT)IdfW?2wk0!{qpo3qFsZ^s6}V z$A50ToTW{=Rz*irc{%Q{{I)v7^tN}rua-N0QuQ1rGj}XcxSdX+S2|@B6faQiF(BM!<;Gg z7CzWIm$2H4j>?;=f$@haJH%%YsOGCHSbrv(P+5WL4f#dn%quK#P+y9Lgg*^He<4W+ zRDG+re~~%tV5a3rDZS1$6_bExG6G|`g{ z2EVZ7B0%fb5j(cH3070=ThfSs41b)QHD`aeYW4Z4Rr9&iTbR1Z% zCb1(3l~JOP>qt98PS4&8C*CIjSfu)I^wF3;Y-CU`zh}y<@|Hd_b1WEiMSox3Q=~+< zJ?gueA80%TCEW`?`5;p;?Ho?Z4kq$RI@N+jpz5!RZEsCeB+bTQZ zXBETu0>UgM5Kc5a3N;2JELF;72Bvy_`8e$|q@FQVKE3!a6I`f4l8o**Wu$t7B^ooqk?0>0_mOy);hCS%K zFrT*+6sTVT{62{QC?HqVWUqrT=S>rLgH@>+V828nx-weDXNR2qGA<8SqNslY1sROB z;_xS&7bTz~P6@B*Tlf)du0T0s|qj)pEw&i&IL{+s9)zBf9O0HW5ANiTJnW6_nIM=2A8x zYWflo(bYrR@JTL7>=OvsGp0vj;rT%jDZ$xm*tlo}bd?-U<$s*GI5hd0(Ug^^@1%Rq z^d_V`pWBAnge<=awa_UYvI#ZPg5j=2cl&ViSa%E@MWfwLl%}`$X$o_19aeCG$mZE< zu;n7qJjniBRGK%99jT%xd8WJqjsWwxoiiz-y5y`~0pIB7lTiOzIYikpg63u3BU+pR z{x2$3jxPjR%zs>_7Q83*v+kCt`2CP)zZ+UycznkBa_kW9_*MWSCxtrTKx}5poFYu- z!Q0dKCdJHaENFuG$!O_ED+fWJX>9l_jrjfh3BTJ9QEXd%gW!tOhdZndloIn?T*g)A zFp<1%!tl3#1z0~`#R!gJY|D-l%tU5UbG&SyKq_b0#(xOnnmWNTg1qJNCx!oS;SS%g+9~p26Wqx6Rk3K7dQ^IM4$?1KYaD(*| z3|W)+Gk@=(9sx^y&|8X+)l1`D=}O0*UyH}K!RXfbs0;H4rkihB-D$}O1)P1wQMYoJ z{3%%ff508kFbO)hLOa^^$Sz9cZ~4oaekkj)R9u^hEN))=JbFbG%)jDVGggX^cp*E0 z4s|F6N1+$7I^D_&!v)>fNROT{fA@#jbomT^n5qK7Xbt_#96~Rt+ooAM>_I6b6>9ACGa7Z~B(1 zo1Iu)v+!{+k@4U`R`yY-NEs$bQ&rI)sS`=Gg0x>9`XAwm1dkv^EB&}GHJ%fQMMVig z%KinBe{@--lRQY79|5w6aTUqg+tZde`FZBUY|#ToxsZmKJom>gUa(5PTCn0g6ndHDL%WH!5H2av~&9 z{WK;Bd-atoXRuowuy)XFnWVxy?$3FUf0*(SZu1zh2C$CVkaUtLMGh8Y`%MJ%Zz;dP zbbke!9o)cjx+%{D!7+wY-trET1M$(2eXQti0JwX!RPVrX$47G?wdgRbk8nlS=cBRnKuc?7}%TN|soSlo)mJM7f zzX1d^NCmTkwU_kPG}>pDgy3B3Pv5ayvKWI#r|+sTdk;X3{JjkzKvjJG8`}?$LG3Jd zUg+!P8zSkLJAiqi^{3xiSR?-WK&`_e!ADP!fRKL`LQVG2?!_h`i+`SZs=UOrvi_Gc zC;qU>j<*UF9gqDc|J7p7;-v$hwwxJ}KN9(1UU>V58#GAeve5&s$ll<+Cpl10s<_AUsOB)(H9zOIqi z^}_{RUgckrdHOI+JAaEZ$(?q)Aj$7~N%-Fu8kNs@Fo_<$M3dc^`TaFvjkx=1NjwTF zs5}nIS!@dq5Y6ouxK|0)>8Ayq&}LVr(1r<~(z_%CTL-Zv@}E|Xy(23M{~JI6f;Cyc zLar$d2@$hs=?W7ccd}SP@N(1#!n%!Fz)cRUSbl-vh(QANCx5Dn$_cIy=IFaiI<9mm z;zU5~_}6i)9OckX03}E~HV9RoEzoQ|jm=pkw6fn@8Yj}Y*kP>JkX(t1(7J)zOcDF_5%`^_2%vhK|HsJ0Z;k7l-4xDiGNL!{IcE6 zKNb<>A7hB8ZH8t;0`+4NDBdv{)$Y_Aw;Lirup(QsxUFJrpLpJvr+7Tp_vHQA`+E>r z-$Aw{y?30!`e$03%jRus*9%` zZ%CCFRoY(B4Ip5mk_ajXs{#*B0Xi!>WYwsNS3&|Ce7L|x^LXmhkwuwPO#HjqCVm45 zcqcHfYh3%gN;Y>f(x=lXAPlFWy3IjzV=+#P&9+b*Sf~ZfJXCp3M7i?4IrSnsD|Zq|Un=nd^Af0^n*^eLmYA_Jq>1Pr5>DX)}g`4p^6oDkNswX_2ieu6deaY0m@%fPs+#d0DtCa zq9y6LW6q-M@dYHFa3EQIf#9lZ=KIWeXHkFxpLSf}RUQ&THstrT$$E)+IrJTe#k!Pc zW5O(Ua*FHg>V5d@CEi*#s!uf)^WO0*& z{#%}x(uUNf^q37Gpj$P5ubA7*Pk$PSm;bJr@2}UK#kdtS?e}!7+!7nfzw;oEZvzM@ zOXMeXSTC1R9NJ%7%k`Bd@7&uL{;}LU1{&?#o z{-tusBB5=dzQc8PTv9+z{Km2{A^7H?Q2vTT%;E&z2K*p~Vf(o;wR<2U$bbLU@Jf26 zgfCG`u00K6hl8$+EN>9vg{%dUJ zJBu|@L<)lxZP?14HVi>=Ju+%kUeh3CL9{m+!M}zorMzn-XE6k!ewU?S;9eYBxUq)z zfoxGeYdU3;f$4db56Cj=M}I0><-1bg#KT6N1AnD0Srpe(>F4iyxq;1qnjPYsD717sUoC3BNVllRF8bpF_w7Bx}itF9|suaqH#Rm3XBWY;24g#_` zLq4Isk<8?8@f0vbtK(axRX(A#5N$Oyi|7GD`)~mlgZdX2=IfaaAb;RH$V83E$f)01 zIKb@^$yw|M9HWlMe?|ElL6q=^2c_fjDAWob?&zFC)N;_niuxSH?IyV@V~&s3Nqn`( zb=G@N1BZ4Guij}gfwPeLg)eZUGGpZ7sKN33epd@Z zl_$t^Bid^06z%?+4u25X5+do-Wr}scEhDvvL|oEptl(~VMsb~B)fF#rTQ-_XqPcvy ze?cX<|My-nFM`(KvW`@5L;^4v*H2K|ZbiD_Hy?s0t=blPn`4xrX3Do;_01SO){WBCda3x8EkW)|zJRNt22AWJi>!GCJ2&S3$G~onU_BCtD|xM75OD-RDO@iE2UsytIS3 zO?1-%qD5P0bbp^sWgxLajJ~4%M;qiC`~*qMgr^vV{<;p3QS-FBEsVBKs$d+-Lc)#8 zU(L$#l};k(VJDeKqID8SQAYJGL}~0?o{Tq$TSdauZgrO+3XSXSMMV2%#}pk;M;Qj? zY=Nbu+wO6QqfWaOo`o#3Wba3m*fnlEqC~%SuY@A3B!5Ib8_d8;Lew)>rqMN`QEn+X zq8(Mo8wk@(6{5s%n5CuEO)}RH0`2?q1=OF#0f~t1uhe(?8EVC$cW{W?UZ zkiYWzaDN@)6^K;cLgo)YHyfg79Yqmc>L;{W@#XTV?jKHxjpUCAA)G1kbpt5!b@>-y z-p&6tXuqonh%Cv3|_7Uk}mol1z~_1JRPjZj<;rM2rzUGTNNJw*drHkULp7Fz>F<%C&9w7*dy-0}qWyFlTazZyF|{H=5-;_UFE{X$WD7sLkk1|J;qTMQvO zQ2H1iQT_%HK)zsEl*`8GVf$2h){0B?TJRoTP{AEf$r2ktfC?2)TRvaWp7rK#*YWwi z9e;EZuVGj(*UZ%K7l|i7s8AiOANfEe{_D(Km(5(#Y&A2XEPlPTQa)0usC+Cr}zbePfD=LTkde$1rg_Njr|DDC=cLXT?LiP(v~cKC*tM3 zUU_%~Mc|Udy0@kCk@$)v%pw6c;CehlsDC`G&^&(nT9O`2R)|);=GNz0LL?nS|7lB1 zqtkE4?d4ZY3DGR3bKo*xl0^!^YW2ZI==aen+M(Q`zQ7E#_gNm=NQWX?y7IJP5Mtt6 zCXI)4E)3f*1o7jOw|Vb931R*>L>4!*pzy7O%YW>f$^X$gJ^U3*V0~hJq_Klr(|;fH zk7p+T@?y36-g0O+Wc`Fz)ZVSXw%bF5edU8qQMqi;{w^!tS){!1X}h{3rMXda`U3{S zhZF7C^C~}_M)IF&2wv`9IQz3;E?Er!g#V1$ez?Q)qAh`mr~vABS0rD4CL!4RPqbuF z#y7BTQIVA99;m%V*MONn937P<9e;xrW^t1#(cW?^2tK>8B>vL0-$k?lbCR^S93=U- zm!;j5Z57cfwL>(-v3?3p50^bkvN(G^emATXasvpc%nYXuQ^4Zg*eyx3aEBs(97nWe zabuRj?d1hR@!TNEPw?~aGfRge4n~i!v!VssRmJ6Zx8ObeYa6M=qi{LZ;Q^zFoU@{Q0y*+?d-nusgHctGCJ+wO}xhSFpv?)9RX3Bp92yhHI>Te_= z%qc3ChrceG@-DVR5eG6;Xv-)As1IR35|6>Xq%)zIr=YAriZ;Z7qJM~l*@NpU7#%%< zRZ#h*RgieWV3f@;g0mO`1b-Pi*JGy6fq$|kiyDuk^fBL|J~v>HAH!36QlU^jf^lg3 ztJlz$aX*XjX+K<{Xt!1(4=2nZqyNH|*-ILp`-fXvPkvNmZZ~Uyvwy_lXK}LVAb3F* zgL^DIIOIQgE*8JNm4BDVs+ND&+iZQty<}15K_&j{&1Ht!o7?M}(r<{Oh!S-h@Udh= z`6~%z^e|9C}z^su>+P-@&maPI2R1an7KT zZ8o-CtV_>X;eJh;B@*Dsv1-`F83LS8jKbNo1mh#oa7e)h5YPoU`;dt4JFZ-w3FD# z_&Q|=w$7Q+0V*KTU0zxQ-Wli)E#4Km0rSzaoq#M3qil2Sv1-}1H3JP9=mH|Z*|MDg z$(`|i@qbYeXATF~874p1aQ!`05OYxJ2KS=n+>(P)KyiIFg-{|#g|_dMbSWd9M4xD3 zb_?kr-W%@1R2iE4jwrD;Xza*R(u-LD#r5*Tp`CTP9lH&BN6;RKb|xPCVH`K7D`)*6Ta3T0e=cYnw*C^sJ=l2%;@2*HT^PN}CZaG%~p zi3(I^9L+k;#wJQk6QxJw0B-hNdGy(cKkJ9WVGM{qe20y2+dS+t$a-^Kq`sp4U|@DEEO`WJc@=V;)+`D zG{9%)`T)3P2<-O>_{HGXd@s17@m?G&N8d4x93Yykh%TE_(QyRYDPzx5(rL`nLe>xW zG-0Ng9gl@V`*3gk6!AKLID?|OEH-yHE`O!Vhc_M}SX1I|lDWQeaRUfgWC+&18s0J7 z!oBdj-D9WOuFwYeMn=+W8g9Bt+#NE(gAp$}|bopv`YX*+Qs+}*G!UePWo zmUep^mg*Lc(L#osXnSMo0uQm-)+>xH+-uDBaL!njBR{`aXrrCDqzOEN2&~UU=_GcS z5YcJ(Tc=0hw%z5<5zAAc(-4rL-u~Cpc{9P}1Ob zg;2#twAU>zoZ5Y+DOeL&OrhO~9KfCFe3AiZPdFml%g6@z`DS3saz99Ctu$xiFbsP&i;PyI?Ogv2BVYKLthkwJH-R|BP zg&lWrmnW0?+WxApLt8mo@RT%YNx|)Pj*h9_9an`MGr0v?RLBG~pjawoezL$y4hXXb z#YNotcUG~5yL0dosX|0*lLfSFh~9*wj*pV>ZPk)NiLK|ckjdr4PY2h(DQy*61EM|O z=id(_LE~~e1_#D~asWY5{J8p2;A+Dzt+ntdgA&PBW}^{p7ZXB>YFRS*SpZcZ>xD2hkGGzH64zd8E+6iQcS#dC5zMmD zi1sf*lo)a{q;~mmmwyFOVtFWu{N!|23eg_P7S<-HERkZnU53Zj3TmAgVA#i;S&5|k*GB;qb1+JCi3P@-dVW`~mlD&6(R zQb@xx5p5O|LW%LIwT+2`>+GBQ_9pOe32q9Q2sEfi}wEEZX`s~5srcOw_}Q91=XW; zJk?Git-T%Rn}3u>1& zZa4|1*A76Nb5YctcUek$`jcF*+_ zYCzMa=(qzs+rHozNas2z1$XP1x$e3fQ3e*0n152x!TI^k0_%sn;rcuI2t}!h5@#3G z6w!|*4es!wO?ogW=VONoF*rZJb+b!4o>5#USA`cnP;bFC>*|zr%eef`KY`W+eSs8_ ze8IKO(CEfTIl_8;Eg_O#1sb7O`MEO9>naX}9ajyfb|1PuHZGUnP0AKkQ(4kztkX6& z4S%jL1_mH*oS6&OSa^kYY8Y+36L__u5maU;o^)JI;gHgChGL)-5Ukr_l1IL3Y#LnO z0|e_fSB-U)krXcD0iwj!Q8q+=ei06g>!hLiJyPQk{V}Ek=NZT6XDRb}Vns;0`^D^b zC&<*pz*9e>L|D{Dh_3#Gggh2lfdp|$lu$Tu{%9)A>0L) zHjQLZVtjTnA@Z|D9V;gvow(iV&NR{#NvpBh)_H@2;$W6p84j+K>-u|&>9pJBdVhE~ zzZTY=lL%3;-&>7zcSkft1o&~a$pX$&5(=bqope{OcQJb5dVCR4wtx`rUr=%$CU9?g z0HVwktWn%<)$n?FA1K9{`K2VD2GMEHw?&Dl?gAHYUXYfwS{QA;1Wlo6^UwgaD=H4{ z->`*_jnB-FX9(7=JHK)>Qy*oyj?8zrTO>i1$s)wY_^tZw__}g|djU~&Oj>GXB#4gV zAV0s9lD7MdcS$c8?*ZIoA}(oEZ?XgK*=gf5^GnFz+pmx#0eg9;cBciMl7H@Byupoj zLY0$!e!tTIhG)G%n+=rLpj(3ja?$j zLMPwZW-dq%0}mx6JrabRjDJb!R2b7+U^;Mycs@pyIB^{*#nSF=@*2-<#?EG}`6(6! z>W7mAiOo#qig&j45~Ondn}=T*8Jh;zA0^~6f4Dc0?*2fn2uB{yh68E$xQ>W3us$ED zZ!fk9MmD$=--c+EB%nms;h1PHzpI_Nq{j~YxcWul#uOb#bfX@{?SFwEqK7K z4I0;1h4;Gxhlt^%XpA ze(%MxaVQ2zGq%qv0yk)KiE^hM8CY2#<`CpRNOXyIu~v*L!m%)$ zzY=*kY=B_vvw>;!Cjv)HV02ZU@_Fn{C{Yyg(s@bzFHnd!{D1n>A7NhQo39zvv@wb! z@fh_ifJiU@tGM0lVS(T+P(kIM6p+QkfJ3wCyG4&86w&S|31epf)FcCg zr@dk^P8+GtgBA`ZpZ4J}Q|VDm3U2L)Pumxq9Td+Xhkvu!(6h&4({L9sk*K$VstP-wmBJ$w07yqHFB49B`lmdg@tWu52 z=n#wq!-4tePWP8p72qqXNwFGr)7#PaY&&|DU4N+bmqSTRV@M%|W?*Cl+YFNu2mk;O z284v-a;a1-pFb1;16D8|N;EtoC?Xsvi$nquK^zW*MS)N#6vj~uN?{lZ5~-Fm`$m`+!Ps3!%h9mF@ygv5sdY=M!T8GliJWT!%1r{ z)AJXLsWw7|RtvR7w>%47dgp@(Bpko;G!5&zA`4fwjzk^@$753g3N^|gq{epriaN`LYOs?x7Tc8;GvjUQk5}W_)Kw28pkXi?Qo%tLj2M7nFdB{H*Q)itAw7;*`tFkBcfln;#)C3| z5?l@L7=r?K=m60$a~<@d=*UXQOzg!;Ia0e{Ya zg*ibDZ9o&finF~c?H4}Nxk_sOWd4KLfmKQC;ZA8}fxWAABQZxOisMreqS>IJqDB<4 z@`s+kv{Vs?(818)x-w?X4TvNmvKTKwvM~HnwbNLt2yMHz%D%qk7(XN@RRpRiXuL2ge@2p;NBv92ah8n|VH!rJ>t+QSKtD;D+Ap$qYx0Y~}$L6pZdWm9y2h$QQM!od951mRbRHC(50ocsrb?ZfsT8*` zzp=hzBfZ6tUK{flYIPhc*b}1s&KT8h@u-hjsT$)UPBUZX6SX^bYc`^yCR*?A1E~3DC2+{r3t6R5b1BC9h4AC*BJzXWXvyu z@f@rn-94OqF`^^a|9!iuCRe6F+G|SuYrsiYeWSRwdB0H;FHEKqjCKvG_HiKs`!q5K zE=2Rd0LtxF6=@-TZ>VcGirpd}4>q=Xm*}vR>;(Iw0XB$kDPg|CEi5Ip6`Ay79|JjY zxm^>p&lv=)(e2h%f9woq&^Etoapm1D<<05*3$97w{_s8NkhFiIigE;r5tuenGzo?% zG3cpX{@jPLemF~)aq|ile>FBUATS_rVrmUMJTFXTZfA68ATl;KH8wszb98cLVQmcx zqm4BRC|u#}FENvcV+9Z^hcn?XfRalhM{L-iyM^r3>2jw|6rAZWOM@TWw*lkaPT$ip`f|qy9 zbdJ+@M_SJoW)ocYGwYE#MTa5*lEX8_YQp3**gN#Q>%_#|NsdQ;v}vSjx8$}H;zi|x zyY@ZoQAY3U*Lkore@Y{_kng;*nd8ZeJWvk10o!V*H4M|#`WL&#KD}s4<}7(Mt0+3@ zwe}x(72sOUC8e!zzRbiX@-fh2lc*?XSbdLk@VhlXDt^3RFo>)QIx#tvm&nLvQ8INklD5#PQxr?Y23D(5H`x zaD?TEwDo)~bnn9Cv2DGfMRX7f4(;8EZUG?;(LvOWfcTK*uJJU94x-u{3#T%vZvmmn z=Oc3iK9JLqe??LD5D(KyxSWzRmv4G7OPY|Ngz(YAm@^0}fm;utaYH&53Tc_U$orF*wnk=GZja7 z%{MGL8hk7G@%}C*+U#vc6*@Y)imT6~a!H%n^Q(6tu&tBT>W2aHIwr@I?q>&cJuHyv z&RSz#f1K)ZEae=1Ia_Wo4pE#2vssr%e%g{TuGGghkI&1+={*?&DU!!*dFJ;hU~a;i zUVi{)N`@JGGn{dHI6q~+@pk`dTMaNV!ng{gw+w}ZgcTrz3~H0eR*q$@AcD?+@)fW+IJOWoe-|rOZ59!{2FO%ZNJ)?_Osi#68U)^p z_`OoKW!bqHWemVRMt56P{k&0!=dcDyk*r;6qc^Iz1P6b8FuP{d*#9t@&VgZ*9X;9R zwwvgR+O5?(DU6Jb;wJe1;IEZLnDktxdYhj84uul|U@3$inYC42Svd9Ixn19x3avMU zf7D$vaiQ@<;%XBhdYYn--#hyP<#ypd&u~)ii^NRxy(G~7cmT7fH5@BzYZ$)F_u9J3 zqOaAduX$?M!v2G*QbiIp_Wol5sG)1z98v5)prlk~okeQK#}XlRj6twe<;e2Y3O#gL zN=wAF3XLgxYaXHegm$9*!0ZX_sPy5jjy&Kf;P?a_w*X&2pufN*FM!BMO3VL}G*QH^8=aI2 zqb!NOz9+EH?@x*ir(D2zjul--Qd(Lztkz77{J!mav{2ePc=WQxp-)_ZmP1`#U9C~s zI)5qjJ|T`d%-zQxf>Dy*_k%}ed!(mR0s|5rce2n9FTYi-x$sa8C8h|m1O=4xEwmBv z5ABK$W`JmQ0Lpc#_O>(GMkqp4;M`N0MnEB4s(`>={5A{lzL3t2jxX4y@rWFXN^VYk-y?+1% zorR-2O@<77clMng|CqfOnVdxkR;-Ot+8h?^wfjS?Vu9;cO4PSPDt`aEpW(Q;Km%Nv zKNS$q(ygyq%E(Q4jFUt^z#n{{4t_HDLsSry+Q?zP5!mvvB6tNu0C5Fr4?S(p8sN8a zZDWJTdv%%S|4R8Z_ z`4_$O%|_}aAio|n)I|4Xg~8+;=h5!X6Zxyx^Gc`u7#q$^=P1MA;3(S{kopsiFj_J^ zM{3(X4D^J|j_b1MD2NaGdHLU$%K>qfc*0l0m;(-Cri}?9v>*cNTrY$m$A8JP@&1O; z!0-a&;0*UU9u?fV>&KtG26a^Gm0@tFsj|&8<#}=f@KC*#a1bKPbV(u5it`JieiZvb z+yMA*;}{GcU5uzOviQ~+0DR&;f>V}vNY7E%?8OSuITa$aef}$c_~vb1d6o080B1%O z2*{&&@grea;2+Lm27^B=rhh=Hoq`g?(G8%-J*XfNDHdpt;0GN~;PK^NDhE&Uw?NPZ zV3l`HS}E1`s^T?nnO%klY@w7#?{>o;YqV=G{wH1wo$vyV59YJdKMT3xa_9A>xm zwajc)>N}r1K@+zDqE6yIh~l?;oqJudENsUL8Yh74GK7XANa0$?heUNCO4RIIUzoyc zeEU+`nslKbj}^Qq>wSO?QV$(v+ij!`Y&IXmzGA*>YV!zi6QAb8p-_5~@e`X5$UK7l z`0f+zTWJB9f4y%Ug?})Cr!F0Q7Y7mp^S=Ys5F!(N=eAq1c^irwDNuc7vWSO8waEL= zr3)tm_~8{R{s7i7`C>!l614d&?Lw&-FZzPWluWT^FXn6HW8ofC%OoEp&NXg~e7Lt5 zR~GSvPywsL;mrA9{va608i5JI3zA2#_*lj03!?&>uH^1b=f+zy*RE?jrp7DB?a8;nR0^=jvOOMd{MFD1oQ>tR)6~7(M>(Jx(uZ z=wQn!yZ4xK8c;q%1@>`0(mJPT{M+b(?T62SAyGI4eROuzzacSf_&QVJ>Y91P-Yx>3y|8Kb|cV36j)Ov>H;3$^1TRn6nHNZ5(#IJPto?;aZ`s(IWZ za1&dZ(q^n{-#bzc-eWtD?`14wL1O!`!*d;q!cUK>NEbE1PzeyxK+uV-y+7)*XKxJ# ziKWSyy?-o7$B!Fmt{H@lAkep^222Ri_BZJYUyj)B%!e4|Ag5^We@Jj=A0DPoG71Qf zg9X9*mPD#j6&|)WjCcx@B%WF70W3%kM(b82vty!1>51wnom?i5hEO>zS1TYJ>Y&(e zm~2toD4wO(WRT45bHiqut)Yo>ylY*q3$xDL8Q4PE{5b&+0l}KX*vY7L1;~cx zSRwg+IyV9j7|vqRMZ&5I@0Y<`B*@EwSy+RWBN7O~eVXd&QOI$nS`5xRf+b=^_kIBS z7VE;b-%=1&(WQDkomQ4V8B61-H;vG0?0>r2UXR3u3q0&R_E6Be4hi)dT@wMdaGjH% zW>8pK_eoU%S|HA91|Cs?2NEI zbcm*K4N_qVNv@6>CiRj#tjJ#0ibP<6D7(rHTH7S!*%VS=A-bi|LcT6R3cd{OxPKJ# zpfFLEH_BDT>Ucx^v+(ZXLpF?t22WLh9 zr!+U7=m@lG)ox$?{CuKg{BW~Uv=iA7sR*AI`#zPD2^JukyX8p88e#_T>uQKho3|Xf zNT2$3eb&iwD!%F%dL~1Ml`{d9RUR{IX!@kdV>qx6kElHms~k_SjNt{uJ}=J=E3xY z@^b!M?d4o_m?yI?J-y^wkkVk04br5_6_(TZVcr)zGMCei0CgA-3h0I4AM@S?0vBgl zd`3Q>d+;J3sBK4zTh)cwZ+}-@l&MkReg2%;oP*-|oOikI)v>5l{Qi4l>&?9KJEk{z zh&n`YEG-hSO3(CacdcfTpnB|h4lnl?R&8jcDPyD~6&DG@sxlS%reM_vzZKsrQa?Z3 zC5Vl}W5O~`vxk92LIjopG*`>N*e96~mxb3Lntl zG@{R;8FWvPMvN%kMwAT*s&PvXpLrEk`P~<&x;e1WZkU(ETv;dLA&bE!)j!|5l2ll%v=!2PC{qV##$dz@Gx`poaJj*J~arG}6NOn-SBYG{HV!DqRYm4#op z#f$h62QNiBSWbV>NJ^Zs`Vz&nlvs*v=lYmTLirRHI`FCfLJ*w;M@>oN_C;BQ6a*&I z@U2bS#0s=fghh98p(Zm659^(c)-+Df@efW^SRR(+jt=|014K3z4Y1?G?TFv`?q*L^ zQXy>G8yc$a6xr_c8}wnP!8EX&GO!nKGOsRC?H}F?~T)FmrC%GE1!wBHTWmZ z;(k`yW&3@8Zk;#EEu2A9Gok%3fD=CjuR;ttQK0Zdu^M4abjImmI5@}9a?q=yk|@bI zpb0y+A%6=g#tDg)vYj|pmr52wpXkWy+;qu4Y9WaL@mVkNK;SAYXXJ@i?_OCQ=aqiR z#F$w=kiwDdlqcA+o!GE1YM$MRlShb25agb-+w9}hens0jIYXc!@IC*5Ozd3|P zIVOqm9!r9zBP$0XO2y-JiIR%7Q+QcxkpbS4Z-4&Y8(n3y@B-JN?$N+fUsiG4iu1vQ zM%gH;juPddj}*a2koiHE3A906@uhg~$2f!DMQtU3EHq|&OVZ=MKvIDiMKKZ2u zNumr=j+?i#wkQ{wIIY~!4M<4na_-)v>eg~v>m)J**R72q{{xxdkwc>l&z=} zD}R_p#K-@T9CGTTf%2Ra)j6CrP(0p;l5I4Toj?aJtgaJJIMgWXZg@SakXHGU3T*QC z7*As3$#xFCk{C}^9Mipbz$Q77cBEYPv&(O0cyKlt9OaPP{-QJcMj?hMj5|*bAGJ!5 zM?|uk96tY4X;mjY8NfD;>ymF3lL);WG=Jc6T2d0VM9S=vIkAM1>z)wCbu{jOg11d6 z|Lh?Vm-A%p>m)~;&#n`sEGO>HhXPJRjWc;n!;;EhdfAV-8412J?LSI>&D)25HK!K^3dyNevMhvC`Tq|+R)4nn z0A$CK^*C~}$x?jH*Tf8)Sa3$xsKm>Vx>!CTRv30to)Cjkhb?%OhiH64Tq-jWYyf!7 zeY#NfV~L(9ww=Wg)E?I5|ds zSddv}{mDtVO~_*W-M=Fy+Xj({41WaI0Ym6^JIG@Ct!FV2-juA&`KPRPI}F*`nSmo( zGeH8F#C1x>Bi`eY$W?|pjUGw8ZXgy0O{l-Nk&Y>);;c0=hL~X31Lw3q1}dHDgn)c^H~yxaIyR*}RYE;dU5Hj8FoU*LC7Ol|_5-<1=LtBKR>LJho1{;J8ZVq;sx{saRh; z(Wh-P$*O~cxpV~vm>ES9V}Cw6G*GB?=6Zs~c|*h&Q|rRl)e7aWfGTDKveU~IrBZVg zdtRdo+P)!eVe6UM(Ap&S&RP(f!6KE4D@#BL=X7rrAGW0GlvWvkxds&!o0zOh`+?Zm zg*9%>aBQe2cHQTQusAu#6oVGIjd+!8*~mASwhI^%tPG1jcIHB#8b;$pA)I5zQ!!gLu*dBF(U)H)vT4s zkzrp-dx9v|=Es9NRGzcSj=j&z7yhA{#2S@rG3@Dh3*a^eNd8Jd{VTzLv2(^c^zxaz zx^C*LY%zR3T2!{vrGG8x8W(yg$=VlPK~TA!E)=>3i0hEw(=zEUUHnA@GEceyFAsgC&Vh142B+-XZmCAb;2o#)BK&J^nXBO%#opNlB{;oNjSpn(zKO+ zn^b*b4WT?0NUC*4gSd9BXdYOtdtnASc0Q2=?mD49-X>!;bfgJ=!xxQxBxO&G26+{b z=ptzzzIE2m`p3flVJG#6kkqV>q#AUHOl+3#{`Ox`B)nlz{0vCQ*uFc+A|l%@4^{$7=;o$MHBgZ#s-*h*5+zFY7p8uJhmE^#ww*o6bfw`>c zgn#EcuRysX6I)A=p^XGs6lgo+ z$=|XJFtpQRaih*vwxs_?ls&#IWBVlOe#uv%Yi9R+_nh?%GoV{2?2_KB^P#4&R>2NG zO^lf({~W`jwYNL##CyPfU1EZj23R3iEq^+sWJvPG4Xb3JBo-d~jA(a9Cu`GbO7coh+YNH$qbGDQ;Jg_};?xp=|F~}GS!Aal^ykp6CD?k_}P=e3oCK!nZ0m+-)QEVQc3?@9g^wxaI@ z;a6I+<_hwOLEBDIp3K$K76dcbP_uC4#omJd?W6|hqH`E8F$j4}&ABHTl6^yj)Zz$@ zI>m_lAI6lV`VEIJ#(&ux8xa;d))DEvmyS{rnnKsDV;aAHu{E=fYx-Qm(U2|1Iq%i@ zt|hP86O#jI)v*}T%e}^AOeP|B@y?-yKgvm*g>tyebKHg2< zk&*t^azv`(MGf$*RA59#c=f~;Drt!hRd3s24M~zkfQP#ol?IK|28v?@am2r*xidj$ z4>b3p_&-r*RQoUs4nfv#U8|S;<71(a1}w6@m#+xpQM0NV((fHCQ?C*{JP`(+DkT*9 zbxqN;@N|zL1AjaW{$sw7W|+b3p?)ye$kCk(DWT>quT{RkgE1|bCfaoU(>v_Jew^*1 zHV6mf>ulVba4^`q8p+9q;302NGVBck@GI%lbzF?!imZ)x&*7_hAWl=sff8Fy5_ziW zj9)U(w}0uT|5#Otmg8(eiJm$Y*j-FPbxiZSiWhkyh5$Ya1b6^&KU#Mnb#m)qQV`|g^L{d~Awe`ihNANwR^GlLwzFXJhG z4q8ghC-#yM_%}Afdd$s*qo0l>ZJ;S^0k-xC_kaG8j=)5I3BFp=h>v@dPg2lB>JjU| zSmimdX`u99taG+UJ!#_5IZj>56{vST_zVRr1Wo~V#VjyZo=v{)Z1~J|Lmq=eXY55| z1lV2n0V9rHa`MYk?wiXORg_^0r}uGhoww7~POEDE402`%|A_4zM-F*JsWl`h_>-oc z*MIS9Os%(24YO|E-h`?R0g)Xz8@hD`Qp0q72w*YI@HmS{e-BjbonB$TJ--Nh3U{cC zomEA=ki_uA;Uu?)WcTQE8W>^8!hc&pS1w3n1!=RmRgYDCwp&G7&J!JJ`$k1*9Hn4) z563)x83A1Jlt+dcw7|-NtIgdP-sy9iJAYsAz7TkZYbZ9QbrMwZ*h1sMP0Ir$8VdTF zLq_uzOpI7j#DS4mF~GND8V*DPj7VfphDTYb#qWfVFudXw$QeyRh5@7dL!@2-LLm^- zaULS0DWdiA3c6AeJ)a_8V~NsMDPJK<7R-3gSD=*OGRZ=T-`m-2%Zx6Yp(%GJ9)FhF zGL^#sMo|?_I^yQ+(l=L729U59PGw)O7vnpM_V~0#n)pUhy~&PT=S9k!2akI@Ckjez4@aPkttl;;2@og{R>ouQZJ=Law;nO%$=UKt#Mja6h z{djc8ab2$kKoak&Rx8)x@XNByYE`(Mh!kN8ZyDL&#VG|V+SHTPtiJ9fdw-6lmsV=^ zezH_w(md+Hmv|JAxyL7k+pITfLCGMaQqjx>0mcExjthGO|AD1OX_#@%_Z$`oI4*^< z3uvC#KN51b$)l5XwcD(7q5On-67MZ&+n7$OkBNgC zFyrf0CSGAh*!C{!DV7|xwtsvfV@m}nJt*;G)xVGh-@-%M?NfRNw(86+uiy@Qo!xF* zy-O2L?BOs|L3?3(PG0@$RG>>J3$0=`3EdC^0OsvUP&K`1d5db;kD|Fy96qFrI&=XJ zsAwvU<{0t88X6V?_RFWDzZz?qqB@herbDxvBq(Y=*m4So=KO@eR(~ZBZB_Xe)dA+d zb>dz4-lCv&@*2svC@LyoN5y?bYEi-3N6nH^uOcZ$)oD4Q^-qop830!w7|9{tj154( z*F0Oeaq+Y7rFlm>F;A?n6BEnX3~lmbR~9)sLtO26f(5w|$kZ5}fdC;BiTVg4l}ZxG zbp1*Kj=MsNIiygq@qfu!^qY_ghfuJgeba?AA~Ld?pur8P(iaqvTd5Q&Geo=(+ddt9 zGFI#XfX}as$h?^ra@GQ)k%(CmEK8Z5)qT%*uC*GPKMewU3g&TcgEF^qtVh zEL)=mqWq{-6ljCP8&g2Z8@2y$kW@bX1Y-fS#r*MgL+Kn>tJxD2FDwa4=a?a#eFB=< z;gZUKcekfP2Fkl?T@)wF)$*TRkYWMYy+bIa03_@*f`2NM8HX$qo;qnNXA#4*-G}z* z;%Z|!Js3m_*v65ymSNq}0j}lku$%f?x(aBnZ0-H#2Ws2R*eMa_(BHHiLas<*!la_8 zN$cLxS%PF8{NQVrH{OsKD`)Sr4f7CZn`j%5q9Thcl0-^zj0iO)*GDP z$gW+DC)_DkjJo)TML^<&SXky0VKV9%W8{4?2Sz8HoEh)Q^`>?a6qkSy3zSZQ!1Kd` ziZ_H=5p+bnmz>{^QVo3 z4;Ij_K_~|cX06sxDgha=!1wThiw zur>3^kQ6CD|vJ92Q7nE^?z2j(EuuERUT>$#~cx#(_1Y9b_J3`z?gup z6xAMjtLA>inXu7+IY1xar^ib;&=W%*CPAC980cPr+~Qne#y>Gg2jF!Se^Vk8UBAkPs#OIKX@NQ+gmD^rIOtd`*AU`HUFG5$l6n#_rKD9I zXg@XCgeJULVv`Kq}T(kkXU|C4GjvLCN*14*==OojH*dDhqmnG z;|(wWvsy**t;wVjd1#pk&cbG2L3=>;$rtr|UqRU*2QjJ9~V9!Ms9fY!2uxp|1hPYM`3uuwrlz7#36XYcnk79MR>8iy`lV zVA)Rm!@l0OzAOX|`boZW700J6h?;2e_^bD5H&2@lgpm9*pj`x#oqP~uRbL$zAF59c zjFC~w0p7!+cX!YH#0wKFUVnB>EMBZ)x@gIPa3mMGUZAC!#_Zg~V(!T_p@#)C1;B^v zu!!QKgK*M4X?YZsB^{kK^h)uG$_X1<2;Gs)V@xeDrTR7}XCHy5>~dz(gkdK_692ci zSpj$ju))0k9q?lg7?$%zFjALCpz|O|T|+uO@<3KtY>zVPJg;)T!GEGO{R@Hn$Jr1FH7SWP?4^Eym1Qw4&AOQST-yu3cR(cO`21#NjIe@IB4B`xjKmj{x zC=bQ0V!p@Xcan@hHLPJ--QSm~3x3i}=z*1_C(-HJpj(cX&|Q@xTGeJoc$Y}dOjRc1 zK?>ZeF?H<0mw#;M1$b1COZYT_f%GWHc5yBav!$8v9cA27%s&|A+jXJm$@(5J|O}&q2478yh zP4vin9`(iQ@8IK!r+!W2&2TXa@d_FW!t|v5WmQsN2|1YNt9)(0utD?e>?HHWC$}_VmW$O0-HIQy?tejN>Yb9Q4rM@K4m+2QtY;3%h?lW) zI7dah5R|P{SRJ%>xosb$Y!1@d$#1)}Q$%$bUQ#%d1a~<;d8dVos5IP8yZ8|-Bm(@T zm{UB$s3F8I&=hh@A#Tlj9>(LxTb{V!D`lo#sAQbJRR&D6llT;aHCv=#M+GH6fH4i< z$bYR*n%Mk?(*}yzNf`3vgyp3YT!_`CVJG|YNqb50tfU8OeIfGGT9S(;4l8~;KNUiZ zNqoN(-#l~OsAl&anw40sBJFUEstzxIalkl}OZE{`+>T#2AwENofxzniYK- zfKaErA5Z$E`&Qd1ZCD%hPuk;gZ|aX|bbmv|!4|a300+o{fn0dxqnLJ?nJUXUX4X-#lTqT6`>-}u{p4Tm82CjgQhESB`3BhJ5aNnb zr>8t1E(b#P)%({c%13Ph4opE2DV4^^^BSs&Bkh9jX{8`{>p_3=LzElD+PLlHmVX}2 zBogI&9K%o6#J6K7OsF(2oF^54NtR6KlTQsVv718hdGZV{Klma2y`mKHNm(`r94m?5 z$^@~b07wNF1%Nic0z{6{0#mfV#X&XS9@i&-df zP*&Idz-br%hlW*@H_27EhK_qZ9)i|j_dOP;OCJf%1&7t4u7+g^dAXN z1Q$7?IyZU}-$_u3!^%wp-$%w^#>#il&{KO}N-H4W5<)mngzh9D@JSC0)ONHWb91Z34N4c=(LV4+Ef zEtm0Qk~^Hf?PN~+q^rbB@SMY})zF{zVe&~RPtqgBL*Gt<3jXZwRDYJ2M>5g?T%(uu z#0(9v!`jgAbE=(O)js)OP2^AV0>b?erW6g4p&G?B35EHrt47cOtme^4nNON$if8`9 z7mJ{gnT065w<*eKe&;u(6CQLjAY@G4cCwULqHQ#jEy_Ir zTZ>?pW2NY+`33-p27hpZiBuj>IQ#(6EFAGi5~ecG$BIsQmqxMP%F>PfCnejnW3ea+ zrM=TVtY*OCz>3jBl!1)=Vo5U3jrnp4c(vRtK~qv7dy2AqkgMZ7dHTu0oAvOB^0{bB zXn=B<$f6015O5{8pat45cv?VmsOyJ$UdGy1U=@kA`kVIM;FNV%7gjqIu;OKZ6 zT0#gdwQ&gzSWk@}$b;gt_cO(l`XrgqZ!n4ZrN?N%_*JC&$@9>=WAtzmV)!}Vd8f8r+vN-=`Zt{_r)f$eFB9!y(X9|; zrxWM)%+A9+ZAAWLdjF<~Z8=~e118dA;u3W4*>7QwpoQ~VW)6-{m6vFYoL|x9JOWLg zW2B3DwvKdxE4-4x;&W70%}@AyTy1FiJ3($a(1AIVhky7pK|_S)h*>y}lro@r>#?bz zUsnS$paJqNYIpK1s#(kfwnXR*5kD#ll4n}xNw=6n5++YS!#smMG8trfAoNPYNv4yo z;%tPdB4VY630fRtn0fYF0fzf6rrRxNfGC;v+(Da-gIR)lHl#ht<-Hu0skP$%NY76{+}ZIgG;G#v!E+77YLmSTx2*uVD30 z#E5Z=RQwYO{K0Yp9_Sufa+OzQZOBEcpOzyBZ+}AEUn7{o(SC|l|KF1}3|D3UWNxhs zD#VNDR-~wm)awj{@~@u?1v7qKFbW5_8U^Bfj8uGnwj2&`TT&-(q~gY@Xj$s=3eiy_ z;9MtC{~m_loFMvgyn6eyCA1NCYDX&d3v78@KEiP8sYsRoMBp(`)W6#+k-{zc&jr}R zDt}p4&(A&~mMkN86{-9aL-(|t8C}N!OrFaZ-4v;I*>cos^jID{NYrd0q4lx!Eomi$ zc(2Wbpj7bh-i{!oowuwn#8n_}*Q#BFkgZ6Mls>`_wrfpz9dsT%)LFaur@8{2iXHwb z`DBKZ2u7ZH#f84w3HQ40(q5%@+4j8#Vt)kkK6yM~vkti=jVZu?xq*AwGZ1wAIxHY) zjomUZ6jAygu#OK&m>)xZ^4TZr1@i+;?%SVCT6GoV;g1bH@TvW?^oPGf?#}|OS2WpA zeFX5)Y8Q;)_Pe{K6C&9^fGLj*otLB?OQU5M`$M};sQQq{k;=Mmf0dX(p=pY`H7W;pa7gH(s z4znoXW(1b5hTEN7tWTavttibvlK)!y86bo2)RmhH`(z|a8DJnqwm+GgD1RGD>65Q> zs&U3ng4$5N?2|DNTW@K|E>O|Q*!p)ig!SX@q|W-}egOn8rU-aPANZ_|P-H+#4;3#< zDt>#LMkC+V9R_|N}{ngS1-JxIOB?g5D)@!`57U zb^VigA&nQ1B{f3{YpiLheHdyyBM{U6&{8X|g@L45tQuSr2;x%&2B`=p5Xv+0ag|h_ z1Ole$>t_F(e`UbA>H^Mr_(zmW-~$dtj3{oODiOpA3*ysJ`&H4%C4a$0IXUvbbyE3235j^m>q{uOIH--RS~T~+EM*m;=>MOTRegz@84M^4 zEvxGyr>`}$6U@xVelidxca*t}*Z^;9+D;BF$ni;`A6LY66wkV=t;%?k0nW?YQjr@& zYbp_bstvV)i_LxDCVxN#IG?m>sXn2gH#wA{547gC$t=RLpVSA8qED2*PT@yWNV=-j zc?^=CCZD54a8TdrGT`qpEmd*VqBS_rs#0Y^NgNv5MrOc-Xzz?umsek3%1;3jdt4$6 zx7zQodYHBZRB*{^aPW^;K$IYz9|#9I@tHb>ai4DFVc>w|K7Z9R5blrx$3h|++mDTH z=L#1~=XZs-%qtZn&vcEom1+8V z<PVvL%_mDu4T)k$sK0vbM%vxmP($|7^Kf zt<{yDX<0jGYwq?s|6s3TFjRc87@K7vATu;EFz-}7mwm~~SQr5TeOtt!LO~`5Mux^> z3J3^HY|Q(DY^m%!21e%X0s(zrh&cfPiFv>{o*FW63t}dM`p!7V?^}M}m=WF&SyTwAY@>Z*@wY7}R&OcWzT{SC$ zUYE`mMbLTagmDFxmrkze(iv2BR#wCn1f9-YP$1~hQkB!wmGum%2r4g~WKPiO4CPrm zy_}#jRK`MOC>BdYxAY9WAsbF~bm^?OtUy&^)~i#P9Ch{N za|Oobb93!E!Nb#a;dPZ|rowA$i$sbNJ2zQobWV;56E|g8Xk=MtDX>gjWqn~ib>$UU zIAzhLlZBKDDIpdvjD~c2%)U}4w!ETC=N6Y#i>xgysjU)HIo~oaETyZg=+gP~<7K8r zM}L>jtt~JUMpLi4>_ktB9;~SqL0V-zXI9w-2_GSvA0cWL%BL&sN^f$| z%$R5s(i=20y2>oYk5ASTi6IbWA+oUiOa)hXMZp`4UtFEcH=nxv$4qMy2=hOSg1 zB^)QE8EQ$VIwz6gjENXi!PTjoutL--)qlxnJ^{9cG+%|RvUDmhVXd+?Y1*W86{W-# z`Z2;<3`QO zbo0}lg-~pT$v<8$q==?F(h=DfXDQ6IXb?`c+0}}u>V>qEMKx9Qg)?@Pq(x;ERn&vx zr)WiqTFiSSt*dBht@T|(i`G)38>=qb>*@elP#0|?h0_=p{bK?vMExN$!9`=OutHQU z3L1$vnj+CgC(w>)ovN`Tx=FTDfqwyIr?d|>3ClX4F!2@D{gOvug{VIxutGZ35m+H= zb#CD`Q%6L%yk;n@5Os?!>Y3#zB_}1Tyj4w7q7o@t3Q>Q4jC_1><{lMhU!LwxH>ayBW3fW)WUbKg&RnPZXMam-t=>r0 zMb(=i6++Y-CKW=|8ys(y$BI^x)@UR|ND*~G^dQknR^KRj>1utNk)B#iS)-nov_)k& zS-NP1SW&$s6HRHF3sqDjeNl&we1?dcv?o$fhmN8^*ltl5n`Gk11yTtILVW2Q7TfMj zhST(9-C1!(t<9RGPjgqQ)qfVD33c(%M<|@aB^ zfx^s6H1!o>g%m=Gs*6h^YpPT;HCajP5JWyu*0UO^sCEi^0wQ9uRYm0F6n!eP8ez$b zx?9=rw=9VT7+F=&(&+=WLg_iXg<`o|?b0b^!))sdg%zS&fm$fdWq(IJL)0o1R)`8U z#3Zu-!E_`Wweb0|E(s9{wTK$|%sowHvd`>7=xj`%JIcogcFw z9$6}dBWC@MSZLo5Cn;y7djpu2A9Psf(+=*`mE_Fcn@~Dy;Ge6;~>( zay6%`D_5sffYn|vtIUF4;tJ7QURHTN;boO`xW=MOXVrue8IE`6N_QNPg78|8swTRs zPFPebtPr(ULE_0;pOEUQlCsJ^*rJ}<8YN}jI?-m=tyc&!tAC24o}45ptIXmm1(Ugm zq^3DtU3s2TvdU-Dnb#YQ(Kp+MnYOvR@4we zR#{74Is>Y@I#s(^A!?NeC`{*vM{Yrag%np(&}`H*Q)wxf(Uo^=Y)XqTnw91dLDL~B z6BJYz9kf-Q(tkZaU-J=^7?g=Ecj|~10+RYphp0$BJc|=_J8G~yWT3Lxk#G>W#x&olGaQ? zL)2P?116$1)HFMSD6D2dMs>9nTH@aH&{+^Y(pss$(F$puvfa4^j(4t&vR|`2Vu+|a zAL)P{(Nmx4luArmV^{Dr$wpf!cxbIuX=i8#(y6J?wj$~yv$;vEOIp)JLsMGEXH1Bi zB{S2a>3_L}*DRl@5Tb6mP$!|M6Y&|OKnXyUTsg}%4i`G_+ z_?pqku!?eI5jBs`RyrM$nX-`P=+gPsrA?~#bbrwyO25EaA>q*HTIJV~)Y z*(nXwQzosSWUVcgSW!LosdJ`7K_Z4gbkRUT^3|yx`$6Lw!cvu(WNQ*qPZup`MKQ@o zOHyLisG*u01QbLM4LLA0rL|F0o+3Jk3ZzqCd4R&?6;etetBrqv4YpqptK}c(%n-yF%HETuNhW+$lv8X4s*`6yptg8cdL}$BP5M6Xo5ItX= ztYHC3_GUP1>e?cZQv46%NS_Nc$3I0YiGN%GUh)KCFu>dfVLL+JosP_)p9wVomm}h~ z51uFEVwK0`C;gT$`3y!f;hRdA^U|arL{RNlz$@f z$P;>nJYwEl#>Ttk$w2@LKZ_@Vy9oEJ}!GA-Dpy?;E$MGS*P*ka(@cu>a^|Ck8uA}{~(D?H-hf@Y}s zeQ>77wiJIEADwuJdy(=d^1n+UAPG4?9{GgF#=+q)l~Q?iIG#)yIVB-Pt9&qI6JqE? zjZYvP1x^nCq`Q~5PGfN3+=y0B!;tV&;i1c_8Lj(;c#fJCOS@%bi>Iz1U| z2|JC0%~oanuf&=Ytik+^#pQ8g*cYhzlPpVxe`P2*FE59Z3mjvnoGhPWeDX7Pc0h1` z$_)3O;gB91wXH+WRem$M!haJo#>dMjzqP6)%Kvm}Q9&UwWKKuUpD;IpI-5^Peu{2` zK&?^RA-pWla-`wsCRKN^i-&g-C=TWVN-^Z}__>Gjo+3DY5NiGQaCKpQr{@%FHJke@q$ zy87-()j%*gNP%c9NKshM9wZLHpqL#&;4)&gvixW*xaL4ng;{wi(Dkewa z1+Fy+heu`~4Uz!CK{Jw8lkyNV?7%vz$1!Jmjr0{j`eyw9Ll*$-+Y!b^!r)y5D$F5v zHUvNcdrKlvL4OE$NJ_xZ<$oI@c_G{!jVCzpcA5#?G-U5U0Tk5+lah#%>2exsfQpu=!?VES5HS7+1INHkke-0BUo7gm*hoPYD|aJ3;;o=alTiL%F^0 zhE#0m+kb6zyAa6*R^@H(l%U}9ze#{Vy{dmm1B|_OR2)t8Hi)~sy99T4cPBt_f(3%R zH|`o_a0w7xgG(6PArLg!;E>?%EP40)?YC$5kKJ=-&aLiSb*rAP>gq1(`?PiMOeH#( z?Y5D9hLaKN?U(K)___tyhPJ68MR~VAR+=)@uY`C9_*Y${!^A?ZrR+qH0U4+$*P$6U zuE9WHRCs`UkPp(&`yAj9MY}(xl?(~1NjD|GK7_{E-NDYu&4mYw`oS#T5eUZGEV{^` zeP1ovr+%r=iT;;kKzD=;C+h_Lb|8XMl&KA#b^b`fopSKCl0lP zAR+p7aH1W8oH-b8-jEI*nksx-0(n%QUwg zWQ>)~czW7aC}rd0V`JkN;C@d@r+vTUp)4bMnN%n6S}JDe$Kb z-6ds7OeX2SjO9E5QLo$QX8Crk1ZLrwj38O73jo`crmpLPh;o-{05|n@{QR|mgZ~xx z)#iL?cXoc(w{({UZ^VC3Y%7*M?F@x8;-rnUV#r6WHwdj%*bJi+ zh@qw4XZjWlwHPuUWqfNlaMF7$9-M9NikMwyY5noB*)1by{>7?cIXiA`OyXT-##DX7 zvDddcL!qi&`@aPwRi0Z5#)d;6yen4HrjeI#wZ32bu0x$2I{YQ;13K)G19^B)I!A9;@A` zao#JRuJu`&u0S+DQXb;8a-S;DKI_tYXjPsta0mGM1O<5eNBMu(dRF)JcN*BF)XL_9 zyEV!iXi1+~gFdOTs?)4>DU$=psY5(MU6kP#Uy!^_zDSU`*if%vPMtW{OtRNvCS%5^ zo!@eC1rsCOu8X*AQ!!@oN(#~)`dD&#-8XK|n@4OHD2Das6=D*Uh(-o_LCy7V|LyPW z?+3PXEW&5Q2a=_z>2gO1lXz`quk49FjzO)hQf^Y4=H;#~{AHPtobK6zN<^e;<0?i- zAm?$KD0l529E)8%l8Yx7_P9F0mck(BnaCG?8Og^H z7(c>@b6-Yw{}eOvYSwq=?C>&?!Sd?yGSol0alf$xa09&Tn;bDoz@5+bE8UBn6&C}+ z_T3<<)(a^h8bthh$B_=4j|%jNo&yYZqWV=e4ZI#hQT^gRyAdhtz!YlhzFCXG+h^FO~$CAEjL{DxtToAhfiyCz_*en`Let6H!B z+f3pG4_g%!=-O<4nK7=jD|SiId#3KI(?rDb@b&D?3zX?$>DRg={b%@$^zNn)b@u2t z*OgP>18V&0Hrkn^9D8`Yhb|?{o4usKrQCY(hpGyP;X0sV*kzS)LcUl-IB7toC>1|q&kYTM}oCE?onf=W84bkub$;M@b2} z%A4s&e^Ez}-6>O&{XASozSrWvoht`pi&E;HZSIJkCpi&AV4Olcd^rxDe7>S;{{&;9 z=bjC^6<|Es_{0Kxu{45jTSB4L&mG){hU!h(9{B;5=I4+!sM(9wS3LBmzY(XRRthP#j?NZ=1Rinjk? z`xKgb*^m^EepJ&s)H3hF4*Nbt9Sch%rU=DoGJ{K~AMG2EWc2B%ChHwT&)0s0)t~@R zRS9mG9vc0Dua|}n?ivEt-eF28(1@>hEoKO_1%j3#^nnDTkmuf3+@DV~vZ#@;D9{l< zmpWqCGghSBx8e~+5(nQ+ZfdHB)#BkVDIq1#e!+)@K~_XsMgHl!J*0ibD9c2o*{0KW zp3ZfTX}o~|sG1_L^5?;i^5~q^f2fB>fQEy^3@dq(Q%G@?K{Wrs1Gi%Hf)#Z4Ie6Is zHfV`yq>g9F`NKE|{oP+n8sP%>!EGcebIj8;A3SpJaH)EYY^?ivu}Qp9D9J?h8yhJF zObR_-KxN*r0On6-Ixf2daX1BO3OmD6ye?;IxT{Vhz+}GrgoYgI$j!{S2So^06K{4B z>;hjgFf#C}f0iqE(stN-WzcHilYqN}7$Z}T?)sYPX=+=UVQ0WK|3V2A zo|vve4HZtV|27c3*}TkJEO0gRlh1NMxqjn^G9hzw7u3?zr{WWJWcimdDk6km(yL^z zgyf!KfXgRNTjA#lsb>{D5{~vB&UPehi?Wt%QPJCHpZ67w*lg?dGt=Qu5^d z0Qs(>t<+$fxh-+dG&N~cS~-<0KbaI>Njew23$P(-ZbkOlh4$Av|4~$ZVW2;vVUtjG zXwYi)M%RFo#U{)wN9pK<7G{mI9w7K9d z4WP}9uv_ddKe@s5bblkj;m0oJP|H+ubKz#@y!awX4g^e*Ql<6odG}c;NDfC1lWpLq zDyrgGNG>@FNt}-pDYa~1NGTxi5_-dJe9%>|869=GZ@dHK(VZi4@1n96o@76TSkhcD zVZ@EyTI=Pn?%1m@lI7zOSGU9S*ZhB3x% zTn*8um4o_-Gg)7vfM68tAER)dZkpP(BJg%xO5vqvdmptq!7`z;;RzZ=V5d}qjkJ_S z1ZWiOKkNC)XX%WZ7%;zFvRwn{(M6>3`PXA}iv&d(?_R55RBW~Jw0R%oHXWhE067$% zgVy-LtmRfT_^Y_Sm94i|D@!T)y@(()pGi&DJnIcEE@$F-!U%olKe}diz8TiUEYrsI zr;DDQyR#o0)2D1&=Q+H7==Ipw8b7}gBP~@`cSlZ|e=wX1>aKT7&*)jTpM37nYjxK% zO8;(l(()3N%KdH#cdyj!o>C%)0bpa~P|7BxQ$~r6zvPNa7ofwTrR9CnC`i z{UyIUN*SZ^0(_;jc+uAFle0zrUjFrq1A~$Ax(CG`pTzfy0il`9Csfr`xzUmsThk|h zZAtUuVL0x967vSN7cNs0;R%n-`Fd(v1@tCFE26CF*Sjv8(d6JTLe*%=BY@twD^=k@ zE(uexd{eUfBFD#iqTG*S*Op|HfdGzA@txKSu4QEwI`Y3a0tGZAA5BiLe$ifEE*XXE zGfGmq+<8HNoQ<@;LaN9_GJ**~8TXe#9D;XqZ%ux2@mmP)l-WMQkG@v=VBf$9f7GGf z_O4w8nqc%`KhH@2)6<9?0Dmi$Y6;3>V=d2=0)EKm#4VWGk-hNgo@HAHp!2na#x-i* zL_VR%-l>A!d5jBDx(}ZXIYq46!X(Y%h==robws&hqk7vqJ0v=OQ20O!f{~YvMmN_< zYwhm0R981Cx>kVDFt5Pi@CbGZnqqnIivOtT#@f0gtFoXqER8a7Lrt~09`qTjFt<&y zaW~Xd6(?0g8hzPIW0LXv`W4di1IqnH%cj@3Fog=;vMWR4;IRIQW}|l|K}?z9N|Zn0 z$=c23M_i_lFqk%ND`9Mfg&~ROlUoSzpMnt>h)yQGrI96ZID>Zz)TmuvIYZC_WFazj zKiPNXs@urlK|{*|lD!CgM}c&*C>kWx6qxCR39l*`?QGCwTX{-_+Gku0;vb5g_mkbXv{;}p&6jef!qJ({g=Q4fzt%W*;J&96I|Kmn;oIBqzdZ1N!BwC|?qGZ4aAy>^9$I@T+E=t&Io=)Qc-_t!!&Qr={e45e zIF_P8lE;0-M7_B)xt}6iPX0-uFDu}J&9yTs`?L#s-8X$`>-D2l(FTHEb|Z#=)y!o3 zW<#^12&qlb_I5Gr;BhmX)zgk%rXGy%QymPf6Y4S`bY8FASm{)?DY`q=ld1X=m8u#* zimZq0`_bWP0zNXB5AxK7jzSX>q%5_$ar3wm;b}A)RCK`tggeWM52CRDnUYYSLgEc5 zwjdd0Ylvgtd{w5+wPH>=&w6Od);;%$KMg4|OD4W^JvVCWl4;BBj6Xb{lz|C)TCyM= z%8~?LMyslG>%p9#72yaDJ4Qnq8dCfr@Kc8aqm~T^-01>}R=dtLNdvZp&GyT${XqD99$Zw{>YZjf?-hQZW1lRF@+U3 zp{Z8uWi_YvhTa~f0g(zeiBSd0UQx~r@tlAvD}$K_=R|6ulIZ$f_==)Svi`k!eQkK! z-@-!K`p{Iu7>Bn3QlPK5G6Lp38Z3P4`g*4(``+86XK{yPYpU$}r^cu4Z*5?Kx(i$O zlye}{$5sU+!e2a>GvMp!FVgjskiGk)XGdDFiYtk)JkLQSqdvN+)Kn6%&R=Z zFER)PO+Q_JPJhs)`1=xUnD&?Rb04c)xkOTaj|uQ5RIi%AHEy}^4;pN9dgKH_9RJ`A z2q`M+FR~&dy!(PxuxNp{m-1@)k2xUbjS!AtyN(E4cNUqy)g#KVi_XsV@p8vV*x+I@ z*a0~h;LDA24j`)&)yQOIQ6wtwmJz~{@cpvlX3G9f-X_&1s_;uQh;|ZvEK9|&v*w{^ zAXhZK^)R#$bze=XWp&O|@j#H8FJJS3kgoKOvF=Nl^Jvb^-JO!?!-|8Z^)GxW6ZyQ{}`uGWoy9OxC+*VFHXI@Nu#2B7-pBi1pU1 zoO>#;icZdM^3xi)gV5r^l5_y)m;^@;lig?VkAA4Q3yJfQJ!hVePN;|Ztet_uzPcJO z4CAC>-oCnD`Ghcx*Wp(czL`mf(y1Z*NOyWY!!4F;O-)O7TSU2aqY#TnQA4%!VYj(vZC*;#{q%xC))C(LEkNHt(zC&;0{lZ_F8M!ArfX&1Hl zK;oLaaFZRA$(U-oxgI0&`u*tLT-=J*)+H*8G-H+1s8JFc$`5)UZV9#3$W90XLQr@Z zLVXJCSv~vSK_5H@ndsS*S8fuysNt%jsjqZo_pWL()x>95A*p7vkGSO2#_8wscbxn; z7>gf+Qdv6h&iD(laa7;-UkSKfjY#z)B01+A$NJI=$+Tl@ybSEcOZGM8eC?taQ6)b z)s#YqB6Yb%&Tt|yG zNo2;I&Cny=V)46m%Z6Au?z%Cyx3z3G$N}3eWNV}HDo0}4t&Evs>J5r&kxPpA1V@Jj z){Nie7T^y_-kDMA2rN*-jxC*Sw&Mvn%3*V>Y zOcC=kkslTX0ap@ZX&7CeIQSrSa}z{U?q$p?AMB=AJS~~>f>gb#Un?HZ_i`*r9 zpc!#VO5@|$^-JbLrA)Mq<%1C$Cyv9c4e(lXR-tPWzfO=$jnH+R-N=3K;?)URHtA^G zd1vsENwy+YX1JLB%81zqenZEaV!&-2Y?t`e4H7ZhMxaV!V{_kV z3M}Hlxl=0#%MnK8(mG1}yP7&CT(Zu-%$h+E$@E)icLV0yGuGwYK1I|X)yT8>lzm2Z z6XhR3Aq?|RV_pcIpZQU!gRs>l$Wnd7nIiX;i|ZK2v4&*5l4p?%`^BSg2gk|e%<%TZ z0(;@cHGn-49Oo4-w}UxMuWRP{8EvG+xG(fxN$WoBNI$6fq7ng&31o69k0V(O%yWJb zPKy6dG{IyhvO7n5aQ-aC^gb9RA?H?J(g-IQ3s#&=v*0$%I}(TzQTc=Y^QCvHcvtGZ zc&4Qz#YNz#q9ChGH0LHPdT-D|0RezV>_^&J0z7MdH~O0p8n5V|1gp3J3b2C#pHS&V z=Ns`Ptht3yAX~6CXv+Sr{)^$+L71WEcK1;l_1oVA?2TPPx-UJ(6zPmmi&cM<tPiV^p1+X$~JYu z%LAI@E(fu}I6w6|dt)W$K0k3cB|O4+pdWH!rW3Qr?BRa>=|oZ62zQ155^wv6MBt0C z5AC9A+e2SkR&6I?TCe*RPF;)q7L~!rRg*4GVdNMwvOmCg)A2AWOx`{?k?zbGgPHDt zKk(T128FM$YXiRKk|;Sex@)&+Dj5Bg_a4BlWJ5-r$Mr-u_*8U7A~j7LoCsrI+-x3| zui_z(L%@BhV)dGIlURskdBymxKc_rZs|}Wo?m2T^0wKts(0!E@m-BY0u*Cpjd%eDn zQE;OB9J3>TdtJArUBJuQ9<qFtyIihp&%I?ed=4pPkzhe+K~F|uPqnv~l*v_2 zjHb=Aae|*Uw{nlgPeJ*PdC1SC1A)@?ARUE|ZvhAjtR~*?@KG69{gwh zP}7CvLvn0zeELEeNu=Ku*Zzmk<=w?nNJ6e?O!{{TI8=oC66w82+Vt ztQHrg<>f|>;uqq0d#eg#e<>-Iwb*XB-^tHPjFM(SU(=Nv<)SQD?Nz-?aQO{hkTpdq zUs4h3&)GKGqge5)pxV@|W|nP28oqs(0qWDv`E7MZb#;+wWJ;+S|Q{#Ipsv4nBxpaNs4C|Ft*6DW{|L;Nm$5~16z>=6PX|SC2{K4ZA}YQ zvhE}lm1PvAJ7~z4TFJ^R0-B-yJ@8sRQ8`(UKYqwEK|# z7|jb|ElKz>urTZ97!Um~qXsoWQ7_FA)(?cR2Ke!8w%n5FTihc!P54B)2Ku1I`!hzsO9U5ORi%Y}{pT61w~ zm^bs!=pv?*(j`h!A^^{^9atozWe&s9)^msbmam)P7Hb9-Cs+%H7pP=nCN9bzDi)OQ zDxpgB-ILB~`)#Fg6Wzp_uS&Ko*grTU;?YmM?W?)`^{s<}+!1!tM95QfoL2q>c8B=e z23^|TI~T)-CT~k^(uCE!Fxt`QR7u;Az3qw^N0fYQp#W!xq!Hk8Lcd~n^VV<#Lz1}S zSK4096vZhMI$MjTkk5&I!HwneRAN@KhRC+zHjL0m;{q)NSv{LV^W-LPn^+%431uux znQDz+TIXlx)E_Yj7OrNn3Wylhgq% zQ6I1FUs%3+dyE@}eR2OZRglTUjIb;)cGeRWfBL&i!B_)6e>UpD+p9@#(;>q#Z+iP& zUtT%CxL!L!%m>YbSYW*l`Y1sW$?@}SK_?nXRJFSN0m~f`+Z~flX7+mDUT{VV45j$$ zd*p-<0zGM)0AUiGQ<*Yh;Uv7R$D!705m=_vrcavn`$KW})2Hvt%hHsOqsGUQ$b#_( zc>)s*6}R=1=8vd4it_FP-^(1dyTngMyyB(LF9rBbUikkOX>90jq%SMO(ty7a2WiSU z!D#ft`A&+|RTtc|aa7e&kIR&-D~2%&Q^3k7t)%%^0KtM7D_2k5R6%m_XlK|tFy6)w z+S|m%93UdLXs#2ehN@#bR-2u$l~OA4=LM-50&3MAS$o^${g_ z?ud1{gi^~kB6eETkMPEFzUUSAmJu4(5S#MA|L(4>eN%6GsR`K*zs z#}YSO1_|t1*N5u6bIOSUG0>JLwd!JPG`6yXA!=eNft?e9DT57daL@Ob8|-S~4NRtO z1`aLPSqeYc^ZQ_INjEeekhb=VHNoUNb^`9IL*Y zT0CXrd8N+GP_g= zjFmHki=FQi;aqY)v--pjZC^$BmxKXa6vKmO^Sv~^Wcw-h_lY}2Q${HH(P=AfEz=kq zn@5)!I30W=S@SQ^p8&f=#TzE_%Wan@5h>Jvi{A9HM5MRn*s9{?xR;Ds&indLdGhFN zv|TY}dTfP7@Rf@JuQ0Ox1_!Cd&QAMst^1-3D;r70xJX}3Bh|Gs5$sII@&P6uBYbTe zWp~rG?{pNv7P(s`Wo+8;=NgG2A)@zbadMWSk33`kzB}rtF_c;T$UTZUW3FLltmZen zd*6Dtq$!T`_?vz91WAhLBWy^f1rbmabM21cW~g69j4peNbJ?t zN8VSwu*)_Nc|?Xr=LHAFhCW+B>kaK&)TCcXpVn>4F%;UQ@IhJVu9zR}h1p>L-dU>rqzQ!unJ5evNDSPtdsTF{n9 zFr5U(IbeALHE6GHY|_0{vv!IzU(}u&G*P3kLfI?Ty$8CO#x-wQ`IKn;X<4T;%~h=$ zmCU1|6Bn@Qbi<`&4N_F%d$EIHLVhUge$^4lTIt!nQ%R*4CLpSh)p}6Scz>=->CsTM zk54t#eT7MRer$EEW~J2tJQlAN{DKp^$-cH%~-z8XwCA$MpVMAG$71&9SK5(_a)XHCCKbO&`~bWeY78p=&hV&t(oT0(|PMSY4}B^A_ORgR9$qdPi8Es*Lc{ zJ6eSAp3(=IA`^Ig>TAtNd2fao!lNpkNOstKe3mfg(xqpY<9aSol z)fox?oyGgUEGqg4du#S9WWOz?wDwu!kVYO$7`8N4bNGfYf;II^8BN~g_eNJE56ZC? zU3Ft5t)q{FHE2(O)?zH0JY@y+4Fp=!xywk)>zLBIpDM;+v9{9P8_soI9)@(^K3NY% zy{V49hKRIwDfp` zGD2p$`yK`tJAI_KXQGH{u<;)bt%w0^)a{xmv+K6Uj3gy|i&Y)voC^9+*uPsp+{4|@ zf7r=26aJ4H35Jg!##mHM5YR)Db&!;L&_JeJ4SuEbg&A08jpYA!#Z?EgyZ-F*iicumCB}QxF0T@uz_e5N&*-7l;-~TX`3^;G?)q*d`xk+ zqEUa?b86v(*k72L+tX>uS(%5aaXQc|^27hOx1Cj!zQB9z&e-c#_KF$*i35Qw)=0sH z1MLjz<(M+;XI#k+)?fppRdm@&?)R-Nw=ca%Yo~+y-RU$J26SG6ox=r!cMwDi%+#sc z*rUo3kxX>}`G-y@4+nt~M;9P#JIWbL{SoH9g16`FcGX95(zTL7A20Ypv{(u5wl?B~ zIE=(%b_*hEIQxF^ZoXo`yNoGfsH6GFVL;UF#?(<)r*_jw2dMj9x!$D5dH?n0Tj7t0 zi=YpVO0S|}W8bfA#MxiM<3y(~0%F-i{@&j)lbdM(jjPHD9wsf0oSOlDlUd7U5G*4N`3CX)WM1EwbjG|W=K8BY z_-%KwV}|Jbg3NR^tlj?orAg`aUW?(HK==2q7SmV$O;^l|sx(0cdKu}lTZm8;S2_Mpp88cv$af_OzZ zZe84A*mjaVsLkizT>0DavfkU|2thY399a{u9pEbC`9l~*2aW$xwal*l+3kDH!twfA z%3n$)dg0;06kZZ%f+e!b(|OG1iMfikskw9!{XSQh=Z45xjN_j;)hP`(xBAd-3xd*NT(+XItNyYSv z48YZE!cIp|p#AZO?3$v4Tv}!c32YKFcCTW}PP!fw{f8g%BfY_6RK0vcQ?PDb<}g=P zip_#Y4;~Ul45&$2&x*$f0^x8xDB8&^EPzef$YfuwHkoTxj-_U?)nsh`lPIHj74Fc^ zzSJlbQWSpQ5W_qypFd^qqNZX6`R{osWmlVODwMP2@CKmHSz;=}lQ3p~;6GKQc? ziv@N4wXx5i8#Q);5Z68uoXi$xF;VSq(dGBK)NyJ(^E$~YQ6H-K;JhdM9po%~?*3+t zbdPo{q5Dn%$A`!x@7YMUxMU_a`7Dq`>(QFZL!T)%Cx0hUbZt<5?;HKbB>0NL2}So> z3G-k72Fu6K2a=S=kbvdp%&FR2%0`Kg2I9O?wCs@)1yU4z!n`CG)e{L zPpoF!r3yJq+rD^3Iy&9UWoWB}%+OYXj}E<8>(Ww|;@ZN0+kXOrA}=bWbCc>aR?V$r ztRaofD+F$D`@n+9m8`v9XW*NraUbe4R4E17bv}A&E=;e(zgw_!?tqAxeMLpdk*a0U zwQYSdvG4$AWqA!UL+y12Uk|3n>uTgIM{HQhzpHc9k`9McuoWvkQ4o-@HsriNe zKT~u4m+-9-2!XsfImO`r%kzH+xj@i}4Ah`Fcg}bJRDzr!E_Y7e|C&m2jWX^3r4Zox zPeJ)F`TvbcP+I0+TN2>?uNVqc+#r_@LTV7J2PYE6|D6BFIcUVm&S`>f?PT@u;Gcr; z-vuE2566Ec;s?chaH^2MsrUr{*%BA$FwppDZ*A%EMpr2B$oVf9P_I53;lB&wh4#+` z|69C&=0KYd$he?FPfo7?ED3-XJUJEr3krg0y*O3=1^EO)n30^!FxhaK$Bja7XK^q+dV=IQuXHK{11J@4a8{8v@~a(pY&|A||W z>wj?bf~d1)ss1nE|0(`O{eJ=%Vb|K%vi^Zy5P$~gLenEzKJSPJKq`-fief9l|W zqle}OL3^R&fPF{XN9)3A4ApvPFZdqO_A$~b&ZXO|7erZ8jL0K*VagZw`FCHA101qE1WRxHO ztsV1ogRmZWsDL9QL=XJI+bI^N(_;pY!&(1RD!F6^=Jx}X4YWXXX0SzP&dY&oP@^=v|4gE&7zWj14@jCU+jp-o9XCGq?F@qo#TY|pMD9Z z(yGnm2Qr*#T`WJK+My=$hooJYkISegen?GOutnXsE48lYoh=>zGm}#18PmK@b3B#N zPIgJz;u0`^I#5qXpklTq{Xp?Sr!lE45bIE?B|zn=SYKoMQ=0E**e$6Cqy>4?p5Ibq zYrrk-twS1(5pjzd^-K7(-DI`cQeX3(@Y2={gP{;=^R&89gDYFhn!{_{5^dBfxeD&f z7!TsfkGwDDlgba0l#?V=Yu>K6Yuwv@g7!5Qh&3h>(vQ&+!JRYO%W*E@-=DU$TJUUC zP&u4_HZC(s+;};hD{9HjUN{^MzZ4wu4*;`ipKUe9Wp8$VAMeDJO1ugyf@D^-Iefo` z8~Gh}LR!O*UmJF-313wjZQWZi_wFv2gCsZLMea{k(3=zY&15_)>Tk}o?-lE^^cPEi zx8$aAJ6ix|za3HKzb}14XWa>|;c3XRtUc>=5^7i?`_RU*qXZUux%tZO%%AU?;RImw zxJFRAchQa8jZ;LPCkcLB{HPEhw&uY_eJhCgjr76HR_ ze!xo9(_hxLDY$qDQrXYfs>UH_^mQQo#V31r!221!JCoU(+F_&mZw!vd))G9aPBV^uwBnC`%|2~`u$LTHWH^mcj1>`O z>7H$icNleRl+~>gv*byoBq!GMb+SIJwP#IoUmvgI5@sZ>9UxU~-Re)mt0I8mDb$j1 z+}b3|V%XV5B=*sdoSC4Wl4zKZla)))Il=qhwu3vZiMna2Iu9}Cw|5~|sWtwJ(}(+U zY%D)KN0|jF@%4W(Ab_Se;&bYH)Ksji_IJB|M5ikTIz4*k^gwKjOBcl;Z>dKcm9M8i zhMC11IjcNR2Qw!AvNY9Za4-RK`*tSFTdl!jVqQzQWoNA4)#68Z+8PvQMe}z|TR6As zYZiO%M#g^^7og@}4$9j#&H6WSC4S$fDJ8TQ8T#eL;#HC=w?Eq^+0=v?NWOC{;%C+( z{6MiRCSGFOLj-H6e^FP{J;gnpH9|BwmO3aE)9gIgjbWCb-eL`z@1zH4Umw10-+ex0 zoyj}ii|Jr=F5N#h(vn!C7$s^DLpLJ9UA&GRzLobOKWX2+5hiv%%um`5e6gokxy2>~ zkM5RCEMXq(|2W0IeL9VD@R9T05U`-1c)h9A_k4-z<9an}S(L;LOm!i2xY}}f@3Hbp zB#JMe()_5vN%Z%0i+=*3A+v$jTtD=y2W5lm#wQ=SY~?w%Xj(*l?>KEet0@(9eME3U zUHkZW^H&UYKE8gX_EDtj>n^#WKH}pNQQU`5mdEs0?!$U9O++hM5$;yzX+>B(h&YlG z1HC$<>PFAI^9NG^(lY_@zym#azA_!x?c<~&6r5tT3!Q&M9+(gO-N|IEwXI$Hvx#}> zqn9-N^$&JOx;OiqcV|7Dtm@0|M&akHt^^JZ-@jzfWVe4$($Tj8L-A8$1{I^LRZtr9Ue;$*M(U<$guDkn9ZhRn~T>)&` z{;qXh4}4-Y_5N-mPgQwB#QrEPX>lXYohP0XXAV_F`=fm1idI+2e=2yLdxh=u2tVWFa?_2o>L#CRy z{EiesekW=N$V*u>jV5u?#og^YLn~cwYw^9uZ~ZFJite!%n8~?dHN8;_iNmzA?CfED zosLg!P6*Q98nrX}m8#CTJDJuUmA~2a)={?eG%9u6I+>8B$at-Z#dj3|wbj`CKRs{3 z)J=E}&|QGPp{_goYClU@EAy7#pr`jZ(o-`Yk5ACf&hHzo1f7tX^6O+L=bE;-u18y% zr)K6$2Mm2#kE4!GmvYzehmrQRybZ>^C+BFRnND{O7=d+k(N6OTh0lHl(-aaNscPqU zd+($pZ+!I2G5pObnvMt;TVXt?YsWP$Ig;x$7UDtIN$R7S&pAXIu79pZ`n- zy!r!~zU$31$3U=Y_@q0b&H~HlF@N5T3?jC*27P~lX~F^K*^{8aol9v>y)*`?9iV%s zf@ryRf3s#nMWRFC)<^Hfl(D+(!lEJ{_4+PVFX>kO(GI%B#|fG8*}iCfxG{6def)HE z$Y0&UJ~qK^Mni&hZsl~Oe+mOnm~X{8#FyKxwM~XKfug9PJHdI z6a^54LPU(V-m6o232FY}aDkj&oLh@qd;Jk&A>GDCWcdaY4NLUl?iW8oE_G?3yRJ2$ zaS}>g1ND0rY8oB8_*9{}BFCfZ^W|L0xlt1Hq?UdHTcG)+cA5n@1`IRAUC( zthtQW(^_Cp{JEJT`czA+75H?s5C9o~4R#Jf&)u>@x04YG1WupKA74$BD(7}Wo3AddEXycKGd8qs?W&OuWOUsVn!yKrBEcjdtq_e|(FfjT>XRgODT%xT$Q? zyQLoRvN*K(1CNWBZcrroJ%ezEWkUzq3S&FP8e%&-=k+H|@moQQxQCS15n4bfLkyfr z`Fs0I!8nfv#(Q;`xv+r;)sGMW9?gzIM5hc98Yx=3(oDvF zBECBlgpeJFBvnICnL^(k$Uz(`LXx%<1zAhFh+Hpd_e)N2C@ty0m4M1xdqv|1&9?G z`BQ}S7!;x-9EKx2Kqd%pK#a=j4W*|KtAZcWj0&FO1$(zCK(7{e%7wV1TDq>vlsaWn zGJBHW+Jyw#g;4&4S+NW0*8<_&j9<`IeAoU%(c$0WaA1cl;4*rc`fIKB9zrl=7lK*c z9t0~tv|cJkh7$i93PgaB<^8)AO2P+m>6YLua5YEpc?0GL@JQ(b)mF3yEs%?`#LkA+ zGJZ&gQSAwv5rn9xB?n2Pw#$Z5a!2S0mSF=UH$o#)!mAsQ-`(IqWPd6g6I{(?Wx98c zw$q1*+Y1yXO_k)XcupO&eagMru!ijH2G`ZXs?Q+YjmbjNeli?$H;rc5a4;ToMrCblv*z| z#aiAnpGXNiWr%*aqz!Q}-qxz+5^-W{rkxCSFMKc*F~$+xSA)pJgt*I)Gy~KLQ=+9I zm<}*gaZg1p0JF=F8StYp^u8H%*KHsK#x~@(1QuWqM{93kL2Kh|^!hE)84?E`{^iv- z>`oAoRCXMkw9k5jdv+rX9^BlvTY+o~skkHxkKZO*{q=^h`s;U?b%sx$8KCvaV7oeKUFd6F z@fQJutk1@ye0rPW?EB(D;J~NU$2;mN;wm|8C)A3F>Pi8wf} zV5gt%yVhghn%HL>h3Sn%qUJh+(g%Iz>*2XJvvSww9z@eC;xoqb&+|b;ETp!1D_{wF zxEIRybJ%vRTN6kGY4G3PmrtnXK<@Qu!acAfAC?ZjWQG->6WIGgnve(n&Ie(L2(~?j zaT+5p7$tv2TMxYv>w>rCIk`hS@o|^^@%yR^%m$hN{0lNKV$@r;_zhg;-7>@?=Xk*l znQq@sZQFK)VB6ttVhgQkS2Ai=uJjJsZ(CUA9W%{uzndrj^nPfz(qllVJfT8G8Q@1=F~3Q;IY2v^uSlCPjpuQ)M<@>!yQP+SK`u|u6GRZvJ*oDA||?2+{B zkRZAyn7JlwxFwkBR3d6tKDs1qxFiI&54{*$N+^52{Q#dpLo=ViDd)3T*}ti9K2&VB z&W2OY?L&2KLsD(Hi$8J^M2SobfCW_30(T^4&*pqe7|cNy(i#PM$Ywd?Ovf55MG9uy zUvWsv*+Uci*+Xve1GM)EqUeJHM7;neX&H5uOX6&)6HNXT(z7id)Eh{ar0;1c(pBlM z?ov1N_1G%nOVYTy5CCy15JV6B-6UC{Bq-24?dl}VXa?()hvviFWn4oKbQ$kAX@l8b z5b~!|zY1x@5{oirpO@U_GY;CmH%lp(U=r*8>!dL)gj@D~fpqcTF$=NYzR{-kCtmUSVsm3C^}kzZ$K;Ow(ibqAWn! z`wHc%3q-bkg{Iu`Pw&M`-hWW9(vHxxhG*M}la1L1|L!C7esjgvQV8o%jRa zjAQAH_bgXn!PK>Ak*3gSkz9XG=W6^re4kSg_#P4ZGzUGmj_WLFXSu0sFc>o&Y9AR! zJo+~&8=<{(Zj=k4U$twD8jxu!i{Xc@0BQZayxA&}G)p=m?|eqo-CKQypfLi@!iS`; zKC7-i>xc^QT&#+!anQhaNAvVRm(?K$5b)I+b{v8C*}!%tV8U`HyK*MN3Z{w*CQvz3 zML82_AG*u|D!`i1B~}`&&j;C2hkUjRNzFt2VG1pHNCH4ekAqX=5r4$Qva-2~K#Za( zn`NUZ^IEYb?2&bbORtfnR7>Eg8Qdai7-nIxafR>)WV7QlM=EHX=II7%)X`n5_GDN8 zpwT+NjlE1R77Dt$L9k1woM(Y!NgTWT(7VIx_s9y}v60zIahIFw=AW_63IFW!#`zDk zeHkQgZU=N1BS1}FqlVbq62^`Wt)7zpcLwGny!wGqlj#AjQqOk8i0;Y}jHNrX4aqz+sQ zs{>5LZ!)`J$yKUAOXSP_%*%$m3ij#tTvgdRI8#nJ#G&2~e%Ugd+o5J*-@>JGflWk5sG14@0Xa4dX|HAHk1?GzzUQKLo9=w2+K_-micU({=&4 zOdM(|JX2aMCR2JW^i3wdNt8NmF@!qpvA4h2TX-x{HNp=r3xx^ME&h+i4pC`tTc;N0 zF2Ymj8i3Q3eY4bub1wwN{)ZX$Z!{9+xPzg{(K4xnnrzE41%B( zz|`Gix6y2Ic=By=RN%Zx{6=AIYb(#W^pQV`r?geYwUT;(!UNO?@@ow%&l1d(|D&j@ zjEbXa)&WA0AW3i!SzLp=TY%sMmk=NX_uvc?SX_bycXzkN0xZtr5L^}(ch}4N{keap z&grRBr>m>FtGj0E=~B%kYHdazX`=@Tqc60TzV^F5?H_kL)}wCot@>w+6&2AJ-gVTq z3f64yzB3!jPw7uD>7ZVYx1x?Kdkp(rbIxJ+a?02N^nUsg$9TR!p&evN=vvOEPqjFdbJXsB+xedHMk$!?ie8}p# z;7;eVP9=xE?9spF;3<4Q&fU+8{huA4y<}R#DBK zV^c4dV^h2$z3OZG3kMoT51b{U&TTydyR@t9!nlf#yaL3k@hncDH-l1qhzCtN@DezKgnNU>ad+$p(%zoC3MS};I?^t(u7S4i09O%8h+ z5cM)6gbB4Cy97T^{@hipuu>?w-Ol>9MZ;rn{1o}PPN9=k3rXb&ebF217;8&Dg+t|3 z#L9gNrrHe}k)95l2k^fzPuScJM_Sr$t$tUq{gujSY3H>Xyy1sXdSy38>MnZ5dNBlH zd1U{JQ%LE|FLn%t0}zgzw*)-9g=Fi_GoxK`e8VCOnX0(CGs!jvOR%P1EwL`vhC1}d zIV;=6Z;BmhD38~+t1HCaGiF$=e;&oLZ&4IgK_yypkwta*fSauq&tkoN$3}%xc~~p& zPPAz!l{xAo9zpOf+FIw(*$Zuf7mysB<2x~=%Kg^{&0@zTL7fS^$d$4Wp?YsG=qE_G zs+m^__4O2OeWGLM1;1AeayZv#q^KvR)cB{IvhkR2h;^D{qS*iSDbgdo%AWW>_t%yTkd{XdWJaP>sCdLCM7O9;Ii4I|5QJJ$$}&80It`EXpR5vfHn)5I zrZCMPNkBWy026C(;X9h|Z|fnKPSalK+>b4NTl;6?2rQUTDUwWSGko!NQODycl~Jzl zZet%z$O*8gqxAgH<@L@Zzr`crT}r+|RM2c6p#aY)#pZ`m3IXhAiu_DjpQ-RD#f@#6 z(4at?kdxpu)rH?|o;Q8b9$nQk91R)HcEU`S62P+xO^7R^P2>Vq=BJ4pDUNa?UAyZ8 zt7S!{YEcQOqrs#!n+#SlaPlGvb)4K+@}r>(9-D7U9^nR6@IeVp-ofTrf6YgkSL&mI zvnhlAr=1>Zak=|)N>OQI)W^#Uov02+S^HgWfd+4;T?XwmCkKL5uS)kNmnsd2J$N^% z;Q!zsiX^pv=3pAK1sAFQtLT9m;rB5Dxi;O5prlU5T$^4-P)DGK?7sjFS+-CnH*>C% z#ZC31T#d(3WP?`%fH}zN@wB!7hM6qpENN)HK~pz+LA{yW>2XjHe!qDYbEZA>0l}Um z2mNyMnnb%9d3QL0r-&Y{jvg^T}}5TyV~Q+XXRl<1#x>>DbIm_+U2ycX#9(>bY#W7n0xRb z?lIP8%kg%6(D63>wy02jD;LO6u=A_^oD8o0Y!~uO?W+xLLYl0i!^GT&=bDCY2+@Shh=mQNjar8qGk*{#*}}=q%1gP75?1JcX$`?-*gn$0X6jF z?6kYLHHP%6-fjS_!Hboz96EYoLYa?kAC*_SI#)V1zT9?dB%nRh_TWM$+@3v}{KoF< z1&O9`?e<^M)VKu&S2+c^*#%eRmoJ~AVzJagrZ7HVfl}_h@BNy z1~vrm?}pOXwzCXVON{B-DA5JlW1&V}#Ga@WI|LE=+Q68<5t0#Y6Fx+>s(<6H0Mo%6 zfkC{Y9a}Xu78Plp^odsly{9x*Cy1%_fvNSGsddJt19iQ%2E`0nRyzq+XnKlb*F%a- z#`w#oe=Ms{5S+{4wMjOArU zG#`b64*=PTA-YF4I5J%gnp$rW@CVM39^)amp(*-k7jdVsBBd{)61F9f5K`?_(yP}c zO$pI^WHQ9cn5safPzxtaobA24v2yli5(UGoD?s~^pZKUhUfQl zF-$-I)d&uxfsn9q z1zK6=Qnl(_P3hh!NU)kLsw@d$h{TqO>~8pN)rl|2MXhB*qa{Y^_bk^IQ>(56-Qzxv zb@gb|VrwlDyGFd51^Q?Y%nF;i>io@}E9rb)Y`apjU4R&SB!Z-fqA;5xl^7+l;SyMP1hlk?eSVq(8|t%-4L%Av>l^B9STn0QpUFads+ytC{?#PqY_L7_^)?SSa_xqI1Fd1`D)u z9^nnkp)-&Nr#RdQ8$~l&QoS(lWX=2isxjtNW>J!<*zq-^@!#hL%;yI4EdZ>+DdxTT z!XZq!Q(H}}l1A*gcAp)-Md#Wff7xCX_mD{!ePs9@Sbki629 zy&{S5PFWW>m_r?+*;lsGWh8;Fe4-u%3!KY}8vf>caNu&Mww~kPn=-iY5vruvO9V<1 z#wbKUtpuB2jo-{q)GuHj5Rjo{yvA#`FV4YHja5Zsuuk<)r}gi)LlSz2v?7BVzaEXr za6@Sy`QUEto!JO&hw%7*#F%>&aNvKCC3}E^&&kS<$xwV8&fe_?rY4EM-er(9EXqZ% z%Zd7MPQA;3Z0l};Pa5SW>wn49iOcljZe8iywhu%e>s$rh`-;~Ac(F_qyxf)ABaU_t z8~b>j>8}h~!J0nyS#1xSl@Lwu9$IfZE!9%yX zs&JPjgDd(*e7_1n00C@6Fkhknru|8!;an~0iL`If_%ry5O`nKUk?J;a@D2A$b?L1Wm(ettPQbgXwMBQZU1b!Bk!z1PP={~H@i*ZN#_?A*YHXvv zQBQ(VvUx(hjh5DmUXl$Kb%@T`SPN8N*H>t|^N=`MCTS0SZs3kQL@z#}6M=uz8Aimk zV9M!GMrI7nok=(CPP}cLET$#p|J~6L`ctLb*pQlDHJ>m(zqb~cC2-0!^IkK< zffq^P9C6hHZeQSwjKur<+)< zbYCK?P-VXm-i;B_H;xox{g_m1ThxgE*)MUaYn&n*c%Sd%CY<#1N|>>&Rn3b~Gh}(I zf)>UrnVoP?U_^jQFnYdU7|m=Zba)pKw#30A*=zVss$xuknKRHup8e*ilf;S6Cto zJ>0cxn90FJDiW;5ni)OTa17RnJzGSnVtezGo5&dAb%IV72Pf=b?qsW0v?{KYcG|mUnP0DBqmD737Pq zimQlGL)~y*`+jKA& z1^-z!Z0DgpCd1rxli9%4bSe^UM4l??{%SZcit78R^U&PJGn}3tuU7kMnh0P>y{S%e zVdsPWP-(9AkD!kF?sbZDYX4?oPZp7BZi7(>Qx41X`Y$2mZL~GoB6&*1F=}<>zVZ1q zQtqxD)bkHyJoJcJZBkhy($g5#z}H}5NN`0zTHQOYAInTL*-!)(7;qQXK=~#cpFHvW zy$C7Iv3mJz%GidnvM~*+p8&*Q$+hW0Yx9?e^e%S1$XD1;J2EVzItntCA*oI8kN*X9 z?)>Z+<=FqX(^IDQS(~vW1HqO9TPXI2&3fZlFRIV}i_bT{53Bh2I^`SH3I4iP&st9d z(OE)i`A5A|MwRP5q(>eVP0+nIsn7EKxz!L1D3fw8r9Q3~Up33_Ne4pY$|HFi z*RJ;*4R?Qs&hk+{!lU|gTbj=+nNLNV_u*?Oe7N?SQyzcJWQX03w>TnV_^lU*CRnvn zX!RK35@SDxhNv)ymetVq_smDDp`HYiJutwD)X{NLv zkQD&UM^$Z6ry@DgO$Pkk?)@&SM0-|<@4ydN5sy}6red6(}$>#`TH8k`jm&W=Yru~So(STPgI8pq*B<$FoM?L;BJh$ZOc9Q@1? zAewu)pAQ_ui5A~zjuq}HzMBepwc?&{EsaWW9<`d%NvA0Uz7j)Bc}` znR@&8^_7j!0#ssRzJ3jtll1IB-^Xlk!T=Q-6*n5pg(h+$n3B>!nIr~yJ0DjAq$Z@z+!d#hZq1tnz~G$OLP%xcAf(t=gO5QO{h%4Dk6k zM{pm0X;XUbUiG*jgFB|)3TSRTag+P({*o4myM!9EzF`*yUixIuYe%!I5{3{l*h6Th z5JK@c>lA~jwHw~9oW>Brx7=FrawOxd;Z|AU!yVDNeTQ?KMcACEb;KuB44|-Kl|rLu{?F4%1Nuc@+v^1o&XsP|r1phhM#aXqjXj(MhC59b3(~k)5A8Z^OGZ^MCRi52% ztf^7)Ky%f_=ptuHR&E;TvDsR=t;#30q^e9zifr{!we%tq+%>-X^Hn?Eez%Hqs5kY4qtj8D-whb|PiUB-g+cawcD+T*+bh~Px?utS-y%Xx4Iqu&`77lM(AAMt^e|GComgEW_+~5 zJ3>PMgYyl~A?ea%hAS!!cg2*+yhNWSNSoqJi4_2d_4nH%_3RbD&QF@r2`rjdX%d3X zQedK{;UaC0{)8L#m9BIEu|S!5UI$Lwf}d{$5TJN0{lrj%}Ihu^Ah0EZ7SXrybh z4X0IGz@;3TE60d4+Nl*%6Plt}B4yu=dKnpe?@f(TSX^!`9sQ_wL3ODZ-)^jJxKXx+ zmj^TtLGq@l^XBcnRXL?Xv;?gvPRTODa9vJ3--)Q?z^b)1Vq=K4p<}ZX(Qylm7a_C@1nz>8Yku}B zbufL^>oqP|-0&(8mM5BQRQLncwb!#0(}-B19z>r%E0-;Z*t9h*7#Ez5ZM zWMS;d^bnr>af>R?6$*E#rPXPYXR>$6CEZic_fwH5QXk=!jDlEP;to4Yv(ungUOq#U zef(147r%G*rXyH?PWn_B^7sxd0~0;fU+7@XnFHGQf6tjGv2)9_ErT(X9xsI_58)gh z*%+T&g^zcfFL{=}3o<2t|I^tt)KCC5Y*6{=xY0gaDco8+T3*N}d)<1$A>Vi&&2t4k z#@)J3Y>u-$)RSt-*@NK@FNgfR_q6=SQ z96Vd%8dd6^WsMRk*pIOywJ0s74H`h3+fGc}dlGR`l$mIB5>CwAdn$jELSTKH%I$%B ze7~#u-@@YqV(sKv9X{Fy2;I+8if)s3$qUsS($@L=QQW;4c`kJ3+WYZsb(JhC29l0N zzMo?vJEh!5<`p#ErR-?swCw29D?Q5UYm{jZ!u|I-eA%dN+6$V0BZ+@%>rs`QnUvM>DBlt^oygo|i-EDD^(?>3ux~nDQAq4sX7AfN)uz z+w@L3(N3!!R}Q+MSb;okJNg%&+a3QD!-yvpyoj&(IO>qU zk|0FYrSf2UBYKiO4)p)f!8+{c+Gj#}g)bwaCao#`R=1b90sMjE!-uZE9EO^Z52R)q zBw9g!VdxV(EsZ-ZKEM*s2rtVHaHzeqGwCL9wU1at=MnAZ?r{DT9&sS_Ty@;+-`X1)p6cUnA552gvX8hy1A?BDro1YJt{scGPd5iU z-{aI>m-3zz*v#pFy6K>8->6EN%`5I`(N&TCY!+cr^C_DqjzO(r)Q^4gKoXV5O)D)_ zd@>lPpS)E_nl~+JS^1YM(uRLKfArJ0UGK`>yhHVqN1=wR*L{VXjlm(8{>|co&l&h8 ztal$J#U;?f37G31SlT}@*^2Y^y6zs5BVmVA2z3f|6v#+#W`q1x$`gt&qcJ72t|BmD|{63x{NM*uQ_3=gEAh;p$49_&T*>tk)Dbo zCOEVtOo~4M6_`W9H4Yavx6g{)Kq^0(cBjw8TxThKO}5xD3%{)JE-Q&}&`IH?i#}vH zGjf%A0l}on99$XL?Tl5}qkv|FeEWd0AY7-=71ylkUBwVYEzKU2g!TNS&J@S?YX2T@I>U`3xa2U%h0< zM$xF7#=fIl9fsl{UeF__DS4KaY%zSEX@(0Ay-3cIlI-Wz$u!-{?(`sz;cNZ336aXJLJ&=6;VN5=oQ@>-Q>=>s z#T3Xq4nkc>zHX$cas&6om0@b<%4ThJ?Z%f-7By-fI>r^wKoMo}U;D(*6(!0yl|4kc z97bJ;O0Hgh#bh9?CbN3ot0Ad6RN_0sUerZ$_^gRlO= zNW~=^TPX@OnR_&uaKQb2@<|y<Qa$G9iVXK^-!};MpAAJProTtRrbz`D&gNs-Fk-;aWG)2 z?`sywPwF4A%W%DhZj8J*M~$@o`;~VZs}PA$o&UoGveeEHdPI@$;v{8mVtV2lJfdY{(b)OB&| zGa#&k%p+*JWx1NU^oQg@8|ku0Zj)L4*wJS?V3r`!Gt$y*_DTM0i(ui`>C1@a(TL}H z^Bv0N;R0$}|4wtaA@=xYdYAdGIOWOv#5VMVXj30*mnp+4DFr$VA}pJOZv=hkBi&tR zIm*oT_&yv_*rALr=lU0*fADoOzl^T9=dD5F&ZkpSsQ!UxwpOhpQ;G`k=thgju&6n9wmqs|shR%_$1H;jLlmLHDl ziJDd_f!MX-VfUK+<*32C!}~zCj-^jjS)S*!BCRuW)C5+ZygtJ;Vmo(}kNEYWx#hZf z;|Jt>$hHNDn?QhS=MAFK6O}sa`~}WA(gQi%BW!##)YwrS}otihZ zUDuLL{lfYnQvlS_hQB=2-ZODNi-zq(Kxf65(iV0y&N3EZ0-9b@nCH*JdOR^ z8TEu6%ObCy;m}S=EZVgE=PImz^lLAmI3O%?|`CJ&cGH|%`2bif_Al_-BaP|v$3tEvR5s!Tt^*nC`D z#b>!L%UgK(wDz7bUHnAa(5>50#7y2ev`7(snR-eP$Cl63{bRwPe1hfB{&#qmu-)Pe zHn!YWWdQ*zxcAX`Nk0YE6K)t#e1whYSTp~;&H{Xe)LioxqJHZFm9C zcO~4e)i7q(loOMA;aebpyZATb88*#CY4sdU`r_+2fkv*O!IkfsUouG|Q37VSyqP@90a_u=8uJRZ)p;u!Da%TLi5w8Gd&04dK!}mEQ>(P(ap^)56xpk=L`^P-6FgMfSlPG;qv=w1sVk?&D z+U!_lZ7l5H3o*FFHZ*0do6E)UU|+sl3J2IdA`qXO+! z&@cv74t0Ci-=YydNnNuBdbiOHR5wt5`L_ZpAS*cwtXI8?L&3?j;no63YL0O(xzK5<9_5BiKdY@I5wSg<~vJ>G;XC+c!ArXgR8!>G5!=t$~;_HL%7aoMAFq!?pXV6jj zyJcNr_-5-UK+PtR+Hsd2{W4wqa<9(gf(F4BwTC*g^OT;6T+y!=5L|}*0Ktge_lRlt z>TE>hRJ?`i9k`~wS&#jt0Iu`=;tx#XkVI^@>warSgx+>Y;yHw&tUf{h)`xjeeP|M@ z5x`i*OqdhuxvCx-w{#6E?raKG?#U%X2Nhk9Q{4q}H&+?D!7})BiuEz3kcxiJr z`j_!LA=u6vgS`IT<)+=S3h$4mS_eUT2-ok%Nun>ozPG;prCrs6JrMln6e*x{CyK=y zW&apfmD>A0;lPAQ&;%TI0n??NJx&z_R&&>!>0AT|pYFLQU{=P`g0Vq)7HAHuOxK-9 z;<7A@OX3b*>}Hz5)Ejju*4W}1C6wPE(X^q-g8Kku-$&g$2gRMh$sK&TOOh@hV(^T76qTCpvWj1-nHzsDp&B4%q*^>U#<)& zk#$73Z+yL)@}o?jkYRn&7f2~1-U?l@JmJZ6T%L)@<&bU8f(O-2EPySDNDyDoM^xFL z{A-o{T64{@`073~+(=yEYsRejjWcFr)#aBz2vPUZ1wReSnB}VGBFhv+r}l7=1@VO> zh|I1mO^B4ao-&zy z4{i7!#4XU`M(&cppZ_K((x0^g`*r;b!Zn^@VLX1iZ4LG4ZF75ZNol+ud9_K4W%dY4 z6nZAq*b53GRYYOQJk`67d3j$EHPbxL)Rp}(-y{OVK090!GvHxUeH_pDN(>xPpn zIkSO#fVhejQrr+E7d5)qlI}Vmpl^pJcM#0YGyOg|rFPJRr=qKU@godOhtNLKfa~7+ zGv2S&8F!ICVPUMaO*Hv1M%$jJavsh;7-@|B3RlKD<273ol&sK~7?Rivh6b$E#HhIA zKS?HXdJ|_X1L6JRTPEP=P+=KBw}@*;1s)z?`H`^~D@PhVo$B{QV5KRt>gW}@=DYZ~ z3D0SO$eCRElnRWR3O)qpyQEsr2B1njquo%R3tOK*p=R6wix<7uM6GWJH;gB%1X*mF z1ac^^U#!{9t$i$u`oU&EQkuKF7UB0<4V=66d|g8xAo6|$NllA=mS?nkk7WT2wkEGg zk5`F^8y)D|sNbSR?5;M)xVW23rOZ+dp6Dj?%A;a=Lb^$gqT=LW((N$euFDo$%t-zi%C?6ylO)31Ux(N*VCKq?p*feS zR5+Q*Xi}x%QfT1jCePAo!^J(8B3DPmScI|upHCIbQZ_wRfOkUAflDB&y+7bFW|*0$ z(Z+r`iTzYlE!c8S0avs&1F=3`bvU^W*}LNX}k z_=NU0n&!M}fZ}g-z2|y+L4l(&uHQE|B!ua{+`ylNi{*HqMEzd5#6259#LG>|@bH|C$1gjZl=`Sj{Sg5P_tjrUY!p13i+K^r>O zFQ`X9j5)CW2x0RHr})i0;pb;xZthps>pMr%&NkR)o!HDX(xN2o9nVUmIQ3?>?qLRu z*lS-NoUIfZF;b#THF$X^es)g~Q|)&wbHhG%Q)aFG%Ro~+55soHI~xHMr*ZawJiiRr z(U1}M_iew_&RBOH*1$Z$@of3LjZJ3XN3MDD8*=B4<|X_6Pvt~F(c{b6{I~idFRfg< zI{sFr23Aqg#u?v?Hu>DtT^Ug6wmO)te1QE(=f;gWNjl@T>9JWH|9DNtlhybZgvQia zla<8zi?4Q+?bFzT-{;AEVA>r)d}=RS^)9bHr&5egyRpmbtgG5xm*ndut_PPjy2G(2 z!*B?}jKGg?l;`^MAy#n^cc!Bxuu1Rny`^LFZQj!ds^pgK>O=beK*2ArXD&|T#Y_?I zLpFB)eL)QJ?Gp;Ch*l02nI#0S0m^7vcyinf`&#aOSE`*#c4^hbkD&v*2j`m7WEfW05@ z%;vPPltju+@Domn*^ONGSEQAHeEuEXxbAliv`u&xFzhWqwI( z!5o#QRV-fZ5yXUh^fBuhrpuX8Vuf-kcg1pbkRfcle-MiFh9&ZRcFgJip0@^bLcGq= z)H@lh!jqtV8u#&fXIQ#M9n10KJR0?b?se;-0F|0r zgtm!T0&`|{ceWvmf6dwKi6f;Aer6PjF0={TaTDz{_o1VHOF;U8o#`NibyQu#-7h#qq+EZgTD7U43{9GMBJr`d=$n4dS^hD2%jl(0r!N-e@NlPoEB8!drf3Wa?V*mgE delta 760947 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%0D>R1BMeXF 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 o@T-5?}+7+ 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�o&irnT`n!KOPTs9?`p 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

&= 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

W|B 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 Date: Thu, 4 Feb 2021 17:57:03 -0500 Subject: [PATCH 071/219] Moved gas-tracker.ts into ./helpers and updated references --- helpers/contracts-helpers.ts | 2 +- gas-tracker.ts => helpers/gas-tracker.ts | 0 helpers/init-helpers.ts | 2 +- helpers/oracles-helpers.ts | 2 +- tasks/full/1_address_provider.ts | 2 +- tasks/full/3_oracles.ts | 2 +- tasks/full/5_initialize.ts | 2 +- tasks/migrations/aave.mainnet.ts | 2 +- tasks/migrations/uniswap.mainnet.ts | 2 +- 9 files changed, 8 insertions(+), 8 deletions(-) rename gas-tracker.ts => helpers/gas-tracker.ts (100%) diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 05cf018e..32efc460 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -18,7 +18,7 @@ import { Artifact as BuidlerArtifact } from '@nomiclabs/buidler/types'; import { verifyContract } from './etherscan-verification'; import { getIErc20Detailed } from './contracts-getters'; import { usingTenderly } from './tenderly-utils'; -import { addGas, totalGas } from '../gas-tracker'; +import { addGas, totalGas } from './gas-tracker'; export type MockTokenMap = { [symbol: string]: MintableERC20 }; diff --git a/gas-tracker.ts b/helpers/gas-tracker.ts similarity index 100% rename from gas-tracker.ts rename to helpers/gas-tracker.ts diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 98eee40d..a5b13aa0 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -26,7 +26,7 @@ import { } from './contracts-deployments'; import { ZERO_ADDRESS } from './constants'; import { isZeroAddress } from 'ethereumjs-util'; -import { addGas } from '../gas-tracker'; +import { addGas } from './gas-tracker'; import { getTreasuryAddress } from './configuration'; export const chooseATokenDeployment = (id: eContractid) => { diff --git a/helpers/oracles-helpers.ts b/helpers/oracles-helpers.ts index 18c5c2e3..a1373b76 100644 --- a/helpers/oracles-helpers.ts +++ b/helpers/oracles-helpers.ts @@ -13,7 +13,7 @@ import {MockAggregator} from '../types/MockAggregator'; import {deployMockAggregator} from './contracts-deployments'; import {chunk, waitForTx} from './misc-utils'; import {getStableAndVariableTokensHelper} from './contracts-getters'; -import { addGas } from '../gas-tracker'; +import { addGas } from './gas-tracker'; export const setInitialMarketRatesInRatesOracleByHelper = async ( marketRates: iMultiPoolsAssets, diff --git a/tasks/full/1_address_provider.ts b/tasks/full/1_address_provider.ts index ad7fefd9..08cc7ea0 100644 --- a/tasks/full/1_address_provider.ts +++ b/tasks/full/1_address_provider.ts @@ -20,7 +20,7 @@ import { formatEther, isAddress, parseEther } from 'ethers/lib/utils'; import { isZeroAddress } from 'ethereumjs-util'; import { Signer, BigNumber } from 'ethers'; import { parse } from 'path'; -import { addGas } from '../../gas-tracker'; +import { addGas } from '../../helpers/gas-tracker'; //import BigNumber from 'bignumber.js'; task( diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index edcef77d..ce830b8c 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -17,7 +17,7 @@ import { getLendingRateOracle, getPairsTokenAggregator, } from '../../helpers/contracts-getters'; -import { addGas } from '../../gas-tracker'; +import { addGas } from '../../helpers/gas-tracker'; 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 77d97128..813a6a3e 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -21,7 +21,7 @@ import { getLendingPoolAddressesProvider, } from '../../helpers/contracts-getters'; import { ZERO_ADDRESS } from '../../helpers/constants'; -import { addGas } from '../../gas-tracker'; +import { addGas } from '../../helpers/gas-tracker'; task('full:initialize-lending-pool', 'Initialize lending pool configuration.') .addFlag('verify', 'Verify contracts at Etherscan') diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index c06ec2f3..a987451c 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -3,7 +3,7 @@ import { checkVerification } from '../../helpers/etherscan-verification'; import { ConfigNames } from '../../helpers/configuration'; import { printContracts } from '../../helpers/misc-utils'; import { usingTenderly } from '../../helpers/tenderly-utils'; -import {totalGas} from '../../gas-tracker'; +import {totalGas} from '../../helpers/gas-tracker'; task('aave:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') diff --git a/tasks/migrations/uniswap.mainnet.ts b/tasks/migrations/uniswap.mainnet.ts index ab795d23..86f3a4c2 100644 --- a/tasks/migrations/uniswap.mainnet.ts +++ b/tasks/migrations/uniswap.mainnet.ts @@ -4,7 +4,7 @@ import {checkVerification} from '../../helpers/etherscan-verification'; import {ConfigNames} from '../../helpers/configuration'; import {EthereumNetworkNames} from '../../helpers/types'; import {printContracts} from '../../helpers/misc-utils'; -import {totalGas} from '../../gas-tracker'; +import {totalGas} from '../../helpers/gas-tracker'; task('uniswap:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') From a9e8350e2315cce135e3bfd118a14914e55ded5e Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 4 Feb 2021 19:55:31 -0500 Subject: [PATCH 072/219] Updated UniAAVEWETH price for tests. --- markets/uniswap/commons.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markets/uniswap/commons.ts b/markets/uniswap/commons.ts index b037f859..fda18c55 100644 --- a/markets/uniswap/commons.ts +++ b/markets/uniswap/commons.ts @@ -30,7 +30,7 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniWETH: oneEther.toFixed(), UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniAAVEWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), From 338e58951a3d9f9fe632f6e20b48f9ab73b004db Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 4 Feb 2021 19:56:36 -0500 Subject: [PATCH 073/219] Updated UniAAVEWETH price in aave market for comparison's sake. --- markets/aave/commons.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index beb0c88a..dc9bce99 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -30,7 +30,7 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniWETH: oneEther.toFixed(), UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniAAVEWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), From c0cb7d06a9464c56ed7a796677fe8a24d2e507be Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 5 Feb 2021 10:20:56 -0500 Subject: [PATCH 074/219] Updated test files --- test/delegation-aware-atoken.spec.ts | 2 +- test/upgradeability.spec.ts | 130 ++++++++++++++++++++++++--- 2 files changed, 117 insertions(+), 15 deletions(-) diff --git a/test/delegation-aware-atoken.spec.ts b/test/delegation-aware-atoken.spec.ts index 0e782495..4d252dc7 100644 --- a/test/delegation-aware-atoken.spec.ts +++ b/test/delegation-aware-atoken.spec.ts @@ -33,7 +33,7 @@ makeSuite('AToken: underlying delegation', (testEnv: TestEnv) => { delegationERC20 = await deployMintableDelegationERC20(['DEL', 'DEL', '18']); delegationAToken = await deployDelegationAwareAToken( - [pool.address, delegationERC20.address, ZERO_ADDRESS, 'aDEL', 'aDEL', ZERO_ADDRESS], + [pool.address, delegationERC20.address, ZERO_ADDRESS, ZERO_ADDRESS, 'aDEL', 'aDEL'], false ); }); diff --git a/test/upgradeability.spec.ts b/test/upgradeability.spec.ts index 28e1c335..95e3a8fe 100644 --- a/test/upgradeability.spec.ts +++ b/test/upgradeability.spec.ts @@ -10,6 +10,7 @@ import { getAToken, getMockStableDebtToken, getMockVariableDebtToken, + getStableDebtToken, getVariableDebtToken, } from '../helpers/contracts-getters'; import { @@ -30,25 +31,25 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { pool.address, dai.address, ZERO_ADDRESS, + ZERO_ADDRESS, 'Aave Interest bearing DAI updated', 'aDAI', - ZERO_ADDRESS, ]); const stableDebtTokenInstance = await deployMockStableDebtToken([ pool.address, dai.address, + ZERO_ADDRESS, 'Aave stable debt bearing DAI updated', 'stableDebtDAI', - ZERO_ADDRESS, ]); const variableDebtTokenInstance = await deployMockVariableDebtToken([ pool.address, dai.address, + ZERO_ADDRESS, 'Aave variable debt bearing DAI updated', 'variableDebtDAI', - ZERO_ADDRESS, ]); newATokenAddress = aTokenInstance.address; @@ -59,8 +60,26 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { it('Tries to update the DAI Atoken implementation with a different address than the lendingPoolManager', async () => { const { dai, configurator, users } = testEnv; + const name = await (await getAToken(newATokenAddress)).name(); + const symbol = await (await getAToken(newATokenAddress)).symbol(); + + const updateATokenInputParams: { + asset: string; + treasury: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + treasury: ZERO_ADDRESS, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newATokenAddress, + }; await expect( - configurator.connect(users[1].signer).updateAToken(dai.address, newATokenAddress) + configurator.connect(users[1].signer).updateAToken(updateATokenInputParams) ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); @@ -68,8 +87,24 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { const { dai, configurator, aDai } = testEnv; const name = await (await getAToken(newATokenAddress)).name(); + const symbol = await (await getAToken(newATokenAddress)).symbol(); - await configurator.updateAToken(dai.address, newATokenAddress); + const updateATokenInputParams: { + asset: string; + treasury: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + treasury: ZERO_ADDRESS, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newATokenAddress, + }; + await configurator.updateAToken(updateATokenInputParams); const tokenName = await aDai.name(); @@ -79,19 +114,53 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { it('Tries to update the DAI Stable debt token implementation with a different address than the lendingPoolManager', async () => { const { dai, configurator, users } = testEnv; + const name = await (await getStableDebtToken(newStableTokenAddress)).name(); + const symbol = await (await getStableDebtToken(newStableTokenAddress)).symbol(); + + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newStableTokenAddress, + } + await expect( configurator .connect(users[1].signer) - .updateStableDebtToken(dai.address, newStableTokenAddress) + .updateStableDebtToken(updateDebtTokenInput) ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); it('Upgrades the DAI stable debt token implementation ', async () => { const { dai, configurator, pool, helpersContract } = testEnv; - const name = await (await getAToken(newATokenAddress)).name(); + const name = await (await getStableDebtToken(newStableTokenAddress)).name(); + const symbol = await (await getStableDebtToken(newStableTokenAddress)).symbol(); - await configurator.updateStableDebtToken(dai.address, newStableTokenAddress); + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newStableTokenAddress, + } + + await configurator.updateStableDebtToken(updateDebtTokenInput); const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses(dai.address); @@ -103,21 +172,54 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { }); it('Tries to update the DAI variable debt token implementation with a different address than the lendingPoolManager', async () => { - const { dai, configurator, users } = testEnv; + const {dai, configurator, users} = testEnv; + + const name = await (await getVariableDebtToken(newVariableTokenAddress)).name(); + const symbol = await (await getVariableDebtToken(newVariableTokenAddress)).symbol(); + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newVariableTokenAddress, + } await expect( configurator .connect(users[1].signer) - .updateVariableDebtToken(dai.address, newVariableTokenAddress) + .updateVariableDebtToken(updateDebtTokenInput) ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); it('Upgrades the DAI variable debt token implementation ', async () => { - const { dai, configurator, pool, helpersContract } = testEnv; + const {dai, configurator, pool, helpersContract} = testEnv; + + const name = await (await getVariableDebtToken(newVariableTokenAddress)).name(); + const symbol = await (await getVariableDebtToken(newVariableTokenAddress)).symbol(); + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newVariableTokenAddress, + } + //const name = await (await getAToken(newATokenAddress)).name(); - const name = await (await getAToken(newATokenAddress)).name(); - - await configurator.updateVariableDebtToken(dai.address, newVariableTokenAddress); + await configurator.updateVariableDebtToken(updateDebtTokenInput); const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( dai.address From dad66ef2d48eb302cf109a3729185fc3e053112f Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 5 Feb 2021 11:19:40 -0500 Subject: [PATCH 075/219] Adapted deployments and tests --- helpers/contracts-deployments.ts | 180 +++++++++++++++++------- helpers/init-helpers.ts | 226 +++++++++++++++++++++--------- tasks/helpers/deploy-new-asset.ts | 2 +- 3 files changed, 288 insertions(+), 120 deletions(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index fb284b35..a2b9b826 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -11,7 +11,6 @@ import { PoolConfiguration, eEthereumNetwork, } from './types'; - import { MintableERC20 } from '../types/MintableERC20'; import { MockContract } from 'ethereum-waffle'; import { getReservesConfigByPool } from './configuration'; @@ -69,6 +68,7 @@ const readArtifact = async (id: string) => { } return (DRE as HardhatRuntimeEnvironment).artifacts.readArtifact(id); }; + export const deployLendingPoolAddressesProvider = async (marketId: string, verify?: boolean) => withSaveAndVerify( await new LendingPoolAddressesProviderFactory(await getFirstSigner()).deploy(marketId), @@ -302,78 +302,111 @@ export const deployDefaultReserveInterestRateStrategy = async ( export const deployStableDebtToken = async ( args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], verify: boolean -) => - withSaveAndVerify( - await new StableDebtTokenFactory(await getFirstSigner()).deploy(...args), +) => { + const instance = await withSaveAndVerify( + await new StableDebtTokenFactory(await getFirstSigner()).deploy(), eContractid.StableDebtToken, - args, + [], verify ); + await instance.initialize( + args[0], + args[1], + args[2], + "18", + args[3], + args[4] + ); + + return instance; +} + + export const deployVariableDebtToken = async ( args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], verify: boolean -) => - withSaveAndVerify( - await new VariableDebtTokenFactory(await getFirstSigner()).deploy(...args), +) => { + const instance = await withSaveAndVerify( + await new VariableDebtTokenFactory(await getFirstSigner()).deploy(), eContractid.VariableDebtToken, - args, + [], verify ); + await instance.initialize( + args[0], + args[1], + args[2], + "18", + args[3], + args[4] + ); + + return instance; +} + + export const deployGenericAToken = async ( - [poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController]: [ + [poolAddress, underlyingAssetAddress, treasuryAddress, incentivesController, name, symbol]: [ + tEthereumAddress, tEthereumAddress, tEthereumAddress, tEthereumAddress, string, - string, - tEthereumAddress + string ], verify: boolean ) => { - const args: [ - tEthereumAddress, - tEthereumAddress, - string, - string, - tEthereumAddress, - tEthereumAddress - ] = [poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController]; - return withSaveAndVerify( - await new ATokenFactory(await getFirstSigner()).deploy(...args), + const instance = await withSaveAndVerify( + await new ATokenFactory(await getFirstSigner()).deploy(), eContractid.AToken, - args, + [], verify ); + + await instance.initialize( + poolAddress, + treasuryAddress, + underlyingAssetAddress, + incentivesController, + "18", + name, + symbol + ); + + return instance; }; export const deployDelegationAwareAToken = async ( - [poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController]: [ + [pool, underlyingAssetAddress, treasuryAddress, incentivesController, name, symbol]: [ + tEthereumAddress, tEthereumAddress, tEthereumAddress, tEthereumAddress, string, - string, - tEthereumAddress + string ], verify: boolean ) => { - const args: [ - tEthereumAddress, - tEthereumAddress, - string, - string, - tEthereumAddress, - tEthereumAddress - ] = [poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController]; - - return withSaveAndVerify( - await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(...args), + const instance = await withSaveAndVerify( + await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(), eContractid.DelegationAwareAToken, - args, + [], verify ); + + await instance.initialize( + pool, + treasuryAddress, + underlyingAssetAddress, + incentivesController, + "18", + name, + symbol + ) + + return instance; }; export const deployAllMockTokens = async (verify?: boolean) => { @@ -390,6 +423,7 @@ export const deployAllMockTokens = async (verify?: boolean) => { [tokenSymbol, tokenSymbol, configData ? configData.reserveDecimals : decimals], verify ); + await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); } return tokens; }; @@ -449,16 +483,29 @@ export const deployWETHGateway = async ( ); export const deployMockStableDebtToken = async ( - args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], + args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], verify?: boolean -) => - withSaveAndVerify( - await new MockStableDebtTokenFactory(await getFirstSigner()).deploy(...args), +) => { + const instance = await withSaveAndVerify( + await new MockStableDebtTokenFactory(await getFirstSigner()).deploy(), eContractid.MockStableDebtToken, - args, + [], verify ); + await instance.initialize( + args[0], + args[1], + args[2], + "18", + args[3], + args[4] + ); + + return instance; +} + + export const deployWETHMocked = async (verify?: boolean) => withSaveAndVerify( await new WETH9MockedFactory(await getFirstSigner()).deploy(), @@ -468,26 +515,53 @@ export const deployWETHMocked = async (verify?: boolean) => ); export const deployMockVariableDebtToken = async ( - args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], + args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], verify?: boolean -) => - withSaveAndVerify( - await new MockVariableDebtTokenFactory(await getFirstSigner()).deploy(...args), +) => { + const instance = await withSaveAndVerify( + await new MockVariableDebtTokenFactory(await getFirstSigner()).deploy(), eContractid.MockVariableDebtToken, - args, + [], verify ); + await instance.initialize( + args[0], + args[1], + args[2], + "18", + args[3], + args[4] + ); + + return instance; +} + + export const deployMockAToken = async ( - args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], +args: [tEthereumAddress, tEthereumAddress, tEthereumAddress,tEthereumAddress, string, string], verify?: boolean -) => - withSaveAndVerify( - await new MockATokenFactory(await getFirstSigner()).deploy(...args), +) => { + const instance = await withSaveAndVerify( + await new MockATokenFactory(await getFirstSigner()).deploy(), eContractid.MockAToken, - args, + [], verify ); + + await instance.initialize( + args[0], + args[2], + args[1], + args[3], + "18", + args[4], + args[5], + ); + + return instance; +} + export const deploySelfdestructTransferMock = async (verify?: boolean) => withSaveAndVerify( diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 55c372a7..39af12ed 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -12,6 +12,7 @@ import { getAToken, getATokensAndRatesHelper, getLendingPoolAddressesProvider, + getLendingPoolConfiguratorProxy, getStableAndVariableTokensHelper, } from './contracts-getters'; import { rawInsertContractAddressInDb } from './contracts-helpers'; @@ -75,11 +76,30 @@ export const initReservesByHelper = async ( let reserveInitDecimals: string[] = []; let reserveSymbols: string[] = []; + let initInputParams: { + aTokenImpl: string, + stableDebtTokenImpl: string, + variableDebtTokenImpl: string, + underlyingAssetDecimals: BigNumberish, + interestRateStrategyAddress: string, + underlyingAsset: string, + treasury: string, + incentivesController: string, + underlyingAssetName: string, + aTokenName: string, + aTokenSymbol: string, + variableDebtTokenName: string, + variableDebtTokenSymbol: string, + stableDebtTokenName: string, + stableDebtTokenSymbol: 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[] = []; @@ -94,6 +114,18 @@ export const initReservesByHelper = async ( ][] = []; const reservesDecimals: string[] = []; + const inputParams: { + asset: string, + rates: [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish + ] + }[] = []; + for (let [assetSymbol, { reserveDecimals }] of reservesChunk) { const assetAddressIndex = Object.keys(tokenAddresses).findIndex( (value) => value === assetSymbol @@ -128,11 +160,23 @@ export const initReservesByHelper = async ( stableRateSlope2, ]); reservesDecimals.push(reserveDecimals); + + inputParams.push({ + asset: tokenAddress, + rates: [ + optimalUtilizationRate, + baseVariableBorrowRate, + variableRateSlope1, + variableRateSlope2, + stableRateSlope1, + stableRateSlope2 + ] + }); } // Deploy stable and variable deployers and save implementations const tx1 = await waitForTx( - await stableAndVariableDeployer.initDeployment(tokens, symbols, incentivesController) + await stableAndVariableDeployer.initDeployment(tokens, symbols) ); tx1.events?.forEach((event, index) => { rawInsertContractAddressInDb(`stableDebt${symbols[index]}`, event?.args?.stableToken); @@ -141,13 +185,7 @@ export const initReservesByHelper = async ( // Deploy atokens and rate strategies and save implementations const tx2 = await waitForTx( - await atokenAndRatesDeployer.initDeployment( - tokens, - symbols, - strategyRates, - treasuryAddress, - incentivesController - ) + await atokenAndRatesDeployer.initDeployment(inputParams) ); tx2.events?.forEach((event, index) => { rawInsertContractAddressInDb(`a${symbols[index]}`, event?.args?.aToken); @@ -158,7 +196,7 @@ export const initReservesByHelper = async ( console.log(' * gasUsed: debtTokens batch', tx1.gasUsed.toString()); console.log(' * gasUsed: aTokens and Strategy batch', tx2.gasUsed.toString()); gasUsage = gasUsage.add(tx1.gasUsed).add(tx2.gasUsed); - + 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) || []; @@ -194,9 +232,9 @@ export const initReservesByHelper = async ( poolAddress, tokenAddresses[symbol], treasuryAddress, + ZERO_ADDRESS, `Aave interest bearing ${symbol}`, `a${symbol}`, - ZERO_ADDRESS, ], verify ); @@ -204,9 +242,9 @@ export const initReservesByHelper = async ( [ poolAddress, tokenAddresses[symbol], + ZERO_ADDRESS, // Incentives controller `Aave stable debt bearing ${symbol}`, - `stableDebt${symbol}`, - ZERO_ADDRESS, + `stableDebt${symbol}` ], verify ); @@ -214,9 +252,9 @@ export const initReservesByHelper = async ( [ poolAddress, tokenAddresses[symbol], + ZERO_ADDRESS, // Incentives controller `Aave variable debt bearing ${symbol}`, `variableDebt${symbol}`, - ZERO_ADDRESS, ], verify ); @@ -242,24 +280,37 @@ export const initReservesByHelper = async ( reserveSymbols.push(symbol); } - // Deploy init reserves per chunks - 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(reserveSymbols, initChunks); + for (let i = 0; i < deployedATokens.length; i ++) { + initInputParams.push({ + aTokenImpl: deployedATokens[i], + stableDebtTokenImpl: deployedStableTokens[i], + variableDebtTokenImpl: deployedVariableTokens[i], + underlyingAssetDecimals: reserveInitDecimals[i], + interestRateStrategyAddress: deployedRates[i], + underlyingAsset: reserveTokens[i], + treasury: treasuryAddress, + incentivesController: ZERO_ADDRESS, + underlyingAssetName: reserveSymbols[i], + aTokenName: `Aave interest bearing ${reserveSymbols[i]}`, + aTokenSymbol: `a${reserveSymbols[i]}`, + variableDebtTokenName: `Aave variable debt bearing ${reserveSymbols[i]}`, + variableDebtTokenSymbol: `variableDebt${reserveSymbols[i]}`, + stableDebtTokenName: `Aave stable debt bearing ${reserveSymbols[i]}`, + stableDebtTokenSymbol: `stableDebt${reserveSymbols[i]}` + }); + } - console.log(`- Reserves initialization in ${chunkedStableTokens.length} txs`); - for (let chunkIndex = 0; chunkIndex < chunkedDecimals.length; chunkIndex++) { + // Deploy init reserves per chunks + const chunkedSymbols = chunk(reserveSymbols, initChunks); + const chunkedInitInputParams = chunk(initInputParams, initChunks); + + const configurator = await getLendingPoolConfiguratorProxy(); + await waitForTx(await addressProvider.setPoolAdmin(admin)); + + console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`); + for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) { const tx3 = await waitForTx( - await atokenAndRatesDeployer.initReserve( - chunkedStableTokens[chunkIndex], - chunkedVariableTokens[chunkIndex], - chunkedAtokens[chunkIndex], - chunkedRates[chunkIndex], - chunkedDecimals[chunkIndex] - ) + await configurator.batchInitReserve(chunkedInitInputParams[chunkIndex]) ); console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`); @@ -267,6 +318,7 @@ export const initReservesByHelper = async ( gasUsage = gasUsage.add(tx3.gasUsed); } + // Set deployer back as admin await waitForTx(await addressProvider.setPoolAdmin(admin)); return gasUsage; @@ -315,6 +367,15 @@ export const configureReservesByHelper = async ( const reserveFactors: string[] = []; const stableRatesEnabled: boolean[] = []; + const inputParams : { + asset: string; + baseLTV: BigNumberish; + liquidationThreshold: BigNumberish; + liquidationBonus: BigNumberish; + reserveFactor: BigNumberish; + stableBorrowingEnabled: boolean; + }[] = []; + for (const [ assetSymbol, { @@ -342,6 +403,16 @@ export const configureReservesByHelper = async ( continue; } // Push data + + inputParams.push({ + asset: tokenAddress, + baseLTV: baseLTVAsCollateral, + liquidationThreshold: liquidationThreshold, + liquidationBonus: liquidationBonus, + reserveFactor: reserveFactor, + stableBorrowingEnabled: stableBorrowRateEnabled + }); + tokens.push(tokenAddress); symbols.push(assetSymbol); baseLTVA.push(baseLTVAsCollateral); @@ -356,24 +427,14 @@ export const configureReservesByHelper = async ( // 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); - const chunkedReserveFactors = chunk(reserveFactors, enableChunks); - const chunkedStableRatesEnabled = chunk(stableRatesEnabled, enableChunks); + const chunkedInputParams = chunk(inputParams, enableChunks); - console.log(`- Configure reserves in ${chunkedTokens.length} txs`); - for (let chunkIndex = 0; chunkIndex < chunkedTokens.length; chunkIndex++) { + console.log(`- Configure reserves in ${chunkedInputParams.length} txs`); + for (let chunkIndex = 0; chunkIndex < chunkedInputParams.length; chunkIndex++) { await waitForTx( await atokenAndRatesDeployer.configureReserves( - chunkedTokens[chunkIndex], - chunkedBase[chunkIndex], - chunkedliquidationThresholds[chunkIndex], - chunkedliquidationBonuses[chunkIndex], - chunkedReserveFactors[chunkIndex], - chunkedStableRatesEnabled[chunkIndex], + chunkedInputParams[chunkIndex], { gasLimit: 12000000 } ) ); @@ -425,8 +486,28 @@ export const initTokenReservesByHelper = async ( let deployedVariableTokens: string[] = []; let deployedATokens: string[] = []; let deployedRates: string[] = []; + let reserveTokens: string[] = []; let reserveInitDecimals: string[] = []; let reserveSymbols: string[] = []; + + let initInputParams: { + aTokenImpl: string, + stableDebtTokenImpl: string, + variableDebtTokenImpl: string, + underlyingAssetDecimals: BigNumberish, + interestRateStrategyAddress: string, + underlyingAsset: string, + treasury: string, + incentivesController: string, + underlyingAssetName: string, + aTokenName: string, + aTokenSymbol: string, + variableDebtTokenName: string, + variableDebtTokenSymbol: string, + stableDebtTokenName: string, + stableDebtTokenSymbol: string, + }[] = []; + const network = process.env.MAINNET_FORK === 'true' ? eEthereumNetwork.main @@ -454,9 +535,9 @@ export const initTokenReservesByHelper = async ( [ poolAddress, tokenAddresses[symbol], + ZERO_ADDRESS, // Incentives controller `Aave stable debt bearing ${symbol}`, - `stableDebt${symbol}`, - ZERO_ADDRESS, + `stableDebt${symbol}` ], verify ); @@ -467,9 +548,9 @@ export const initTokenReservesByHelper = async ( [ poolAddress, tokenAddresses[symbol], + ZERO_ADDRESS, // Incentives Controller `Aave variable debt bearing ${symbol}`, - `variableDebt${symbol}`, - ZERO_ADDRESS, + `variableDebt${symbol}` ], verify ); @@ -485,9 +566,9 @@ export const initTokenReservesByHelper = async ( poolAddress, tokenAddresses[symbol], treasuryAddress, - `Aave interest bearing ${symbol}`, - `a${symbol}`, ZERO_ADDRESS, + `Aave interest bearing ${symbol}`, + `a${symbol}` ], verify ); @@ -531,34 +612,47 @@ export const initTokenReservesByHelper = async ( deployedStableTokens.push(stableTokenImpl); deployedVariableTokens.push(variableTokenImpl); deployedATokens.push(aTokenImplementation); + reserveTokens.push(); deployedRates.push(strategyImpl); reserveInitDecimals.push(decimals.toString()); reserveSymbols.push(symbol); } - // Deploy init reserves per chunks - 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(reserveSymbols, initChunks); + for (let i = 0; i < deployedATokens.length; i ++) { + initInputParams.push({ + aTokenImpl: deployedATokens[i], + stableDebtTokenImpl: deployedStableTokens[i], + variableDebtTokenImpl: deployedVariableTokens[i], + underlyingAssetDecimals: reserveInitDecimals[i], + interestRateStrategyAddress: deployedRates[i], + underlyingAsset: tokenAddresses[reserveSymbols[i]], + treasury: treasuryAddress, + incentivesController: ZERO_ADDRESS, + underlyingAssetName: reserveSymbols[i], + aTokenName: `Aave interest bearing ${reserveSymbols[i]}`, + aTokenSymbol: `a${reserveSymbols[i]}`, + variableDebtTokenName: `Aave variable debt bearing ${reserveSymbols[i]}`, + variableDebtTokenSymbol: `variableDebt${reserveSymbols[i]}`, + stableDebtTokenName: `Aave stable debt bearing ${reserveSymbols[i]}`, + stableDebtTokenSymbol: `stableDebt${reserveSymbols[i]}` + }); + } - console.log(`- Reserves initialization in ${chunkedStableTokens.length} txs`); - for (let chunkIndex = 0; chunkIndex < chunkedDecimals.length; chunkIndex++) { + // Deploy init reserves per chunks + const chunkedSymbols = chunk(reserveSymbols, initChunks); + const chunkedInitInputParams = chunk(initInputParams, initChunks); + + const configurator = await getLendingPoolConfiguratorProxy(); + await waitForTx(await addressProvider.setPoolAdmin(admin)); + + console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`); + for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) { const tx3 = await waitForTx( - await atokenAndRatesDeployer.initReserve( - chunkedStableTokens[chunkIndex], - chunkedVariableTokens[chunkIndex], - chunkedAtokens[chunkIndex], - chunkedRates[chunkIndex], - chunkedDecimals[chunkIndex] - ) + await configurator.batchInitReserve(chunkedInitInputParams[chunkIndex]) ); console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`); console.log(' * gasUsed', tx3.gasUsed.toString()); - gasUsage = gasUsage.add(tx3.gasUsed); } // Set deployer back as admin diff --git a/tasks/helpers/deploy-new-asset.ts b/tasks/helpers/deploy-new-asset.ts index 912ebff1..5df35fdc 100644 --- a/tasks/helpers/deploy-new-asset.ts +++ b/tasks/helpers/deploy-new-asset.ts @@ -53,9 +53,9 @@ WRONG RESERVE ASSET SETUP: poolAddress, reserveAssetAddress, treasuryAddress, + ZERO_ADDRESS, `Aave interest bearing ${symbol}`, `a${symbol}`, - ZERO_ADDRESS, ], verify ); From 2601dbb2dfb7489c3edd2f0717504119b80d94ea Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 5 Feb 2021 21:51:12 -0500 Subject: [PATCH 076/219] Updated helpers --- helpers/contracts-helpers.ts | 8 +- helpers/init-helpers.ts | 187 +++++++++++++++-------------------- helpers/oracles-helpers.ts | 24 ++--- 3 files changed, 89 insertions(+), 130 deletions(-) diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 32efc460..d8525861 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -18,7 +18,6 @@ import { Artifact as BuidlerArtifact } from '@nomiclabs/buidler/types'; import { verifyContract } from './etherscan-verification'; import { getIErc20Detailed } from './contracts-getters'; import { usingTenderly } from './tenderly-utils'; -import { addGas, totalGas } from './gas-tracker'; export type MockTokenMap = { [symbol: string]: MintableERC20 }; @@ -90,9 +89,6 @@ export const withSaveAndVerify = async ( args: (string | string[])[], verify?: boolean ): Promise => { - addGas(instance.deployTransaction.gasLimit); - console.log("Current totalGas value:", totalGas); - console.log("Logged gas limit:", instance.deployTransaction.gasLimit); await waitForTx(instance.deployTransaction); await registerContractInJsonDb(id, instance); if (usingTenderly()) { @@ -167,8 +163,8 @@ export const getParamPerPool = ({ proto, uniswap }: iParamsPerPool, pool: switch (pool) { case AavePools.proto: return proto; - case AavePools.uniswap: - return uniswap; + case AavePools.uniswap: + return uniswap; default: return proto; } diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index a5b13aa0..39af12ed 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -26,8 +26,6 @@ import { } from './contracts-deployments'; import { ZERO_ADDRESS } from './constants'; import { isZeroAddress } from 'ethereumjs-util'; -import { addGas } from './gas-tracker'; -import { getTreasuryAddress } from './configuration'; export const chooseATokenDeployment = (id: eContractid) => { switch (id) { @@ -56,7 +54,6 @@ export const initReservesByHelper = async ( const poolAddress = await addressProvider.getLendingPool(); // Set aTokenAndRatesDeployer as temporal admin - addGas(await addressProvider.estimateGas.setPoolAdmin(atokenAndRatesDeployer.address)); await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address)); // CHUNK CONFIGURATION @@ -79,7 +76,6 @@ export const initReservesByHelper = async ( let reserveInitDecimals: string[] = []; let reserveSymbols: string[] = []; - // TEST START let initInputParams: { aTokenImpl: string, stableDebtTokenImpl: string, @@ -97,7 +93,6 @@ export const initReservesByHelper = async ( stableDebtTokenName: string, stableDebtTokenSymbol: string, }[] = []; - // TEST END console.log( `- Token deployments in ${reservesChunks.length * 2} txs instead of ${ @@ -118,7 +113,7 @@ export const initReservesByHelper = async ( BigNumberish ][] = []; const reservesDecimals: string[] = []; - // TEST START + const inputParams: { asset: string, rates: [ @@ -130,7 +125,7 @@ export const initReservesByHelper = async ( BigNumberish ] }[] = []; - // TEST END + for (let [assetSymbol, { reserveDecimals }] of reservesChunk) { const assetAddressIndex = Object.keys(tokenAddresses).findIndex( (value) => value === assetSymbol @@ -166,7 +161,6 @@ export const initReservesByHelper = async ( ]); reservesDecimals.push(reserveDecimals); - // TEST START inputParams.push({ asset: tokenAddress, rates: [ @@ -178,10 +172,8 @@ export const initReservesByHelper = async ( stableRateSlope2 ] }); - // TEST END } - // tx1 and tx2 gas is accounted for later. // Deploy stable and variable deployers and save implementations const tx1 = await waitForTx( await stableAndVariableDeployer.initDeployment(tokens, symbols) @@ -219,29 +211,6 @@ export const initReservesByHelper = async ( reserveSymbols = [...reserveSymbols, ...symbols]; } - // TEST START - for (let i = 0; i < deployedATokens.length; i ++) { - initInputParams.push({ - aTokenImpl: deployedATokens[i], - stableDebtTokenImpl: deployedStableTokens[i], - variableDebtTokenImpl: deployedVariableTokens[i], - underlyingAssetDecimals: reserveInitDecimals[i], - interestRateStrategyAddress: deployedRates[i], - underlyingAsset: reserveTokens[i], - treasury: treasuryAddress, - incentivesController: ZERO_ADDRESS, - underlyingAssetName: reserveSymbols[i], - aTokenName: `Aave interest bearing ${reserveSymbols[i]}`, - aTokenSymbol: `a${reserveSymbols[i]}`, - variableDebtTokenName: `Aave variable debt bearing ${reserveSymbols[i]}`, - variableDebtTokenSymbol: `variableDebt${reserveSymbols[i]}`, - stableDebtTokenName: `Aave stable debt bearing ${reserveSymbols[i]}`, - stableDebtTokenSymbol: `stableDebt${reserveSymbols[i]}` - }); - } - // TEST END - - // Deploy delegated aware reserves tokens const delegatedAwareReserves = Object.entries(reservesParams).filter( ([_, { aTokenImpl }]) => aTokenImpl === eContractid.DelegationAwareAToken @@ -311,42 +280,46 @@ export const initReservesByHelper = async ( reserveSymbols.push(symbol); } - // Deploy init reserves per chunks - 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(reserveSymbols, initChunks); + for (let i = 0; i < deployedATokens.length; i ++) { + initInputParams.push({ + aTokenImpl: deployedATokens[i], + stableDebtTokenImpl: deployedStableTokens[i], + variableDebtTokenImpl: deployedVariableTokens[i], + underlyingAssetDecimals: reserveInitDecimals[i], + interestRateStrategyAddress: deployedRates[i], + underlyingAsset: reserveTokens[i], + treasury: treasuryAddress, + incentivesController: ZERO_ADDRESS, + underlyingAssetName: reserveSymbols[i], + aTokenName: `Aave interest bearing ${reserveSymbols[i]}`, + aTokenSymbol: `a${reserveSymbols[i]}`, + variableDebtTokenName: `Aave variable debt bearing ${reserveSymbols[i]}`, + variableDebtTokenSymbol: `variableDebt${reserveSymbols[i]}`, + stableDebtTokenName: `Aave stable debt bearing ${reserveSymbols[i]}`, + stableDebtTokenSymbol: `stableDebt${reserveSymbols[i]}` + }); + } + + // Deploy init reserves per chunks + const chunkedSymbols = chunk(reserveSymbols, initChunks); + const chunkedInitInputParams = chunk(initInputParams, initChunks); - // TEST START const configurator = await getLendingPoolConfiguratorProxy(); await waitForTx(await addressProvider.setPoolAdmin(admin)); - const chunkedInitInputParams = chunk(initInputParams, initChunks); - // TEST END - console.log(`- Reserves initialization in ${chunkedStableTokens.length} txs`); - for (let chunkIndex = 0; chunkIndex < chunkedDecimals.length; chunkIndex++) { + console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`); + for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) { const tx3 = await waitForTx( - // await atokenAndRatesDeployer.initReserve( - // chunkedStableTokens[chunkIndex], - // chunkedVariableTokens[chunkIndex], - // chunkedAtokens[chunkIndex], - // chunkedRates[chunkIndex], - // chunkedDecimals[chunkIndex] - // ) await configurator.batchInitReserve(chunkedInitInputParams[chunkIndex]) - ); console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`); console.log(' * gasUsed', tx3.gasUsed.toString()); gasUsage = gasUsage.add(tx3.gasUsed); } - addGas(gasUsage); + // Set deployer back as admin - addGas(await addressProvider.estimateGas.setPoolAdmin(admin)); await waitForTx(await addressProvider.setPoolAdmin(admin)); return gasUsage; }; @@ -393,7 +366,7 @@ export const configureReservesByHelper = async ( const liquidationBonuses: string[] = []; const reserveFactors: string[] = []; const stableRatesEnabled: boolean[] = []; - // TEST START + const inputParams : { asset: string; baseLTV: BigNumberish; @@ -402,7 +375,6 @@ export const configureReservesByHelper = async ( reserveFactor: BigNumberish; stableBorrowingEnabled: boolean; }[] = []; - // TEST END for (const [ assetSymbol, @@ -432,7 +404,6 @@ export const configureReservesByHelper = async ( } // Push data - // TEST START inputParams.push({ asset: tokenAddress, baseLTV: baseLTVAsCollateral, @@ -441,7 +412,6 @@ export const configureReservesByHelper = async ( reserveFactor: reserveFactor, stableBorrowingEnabled: stableBorrowRateEnabled }); - // TEST END tokens.push(tokenAddress); symbols.push(assetSymbol); @@ -453,42 +423,15 @@ export const configureReservesByHelper = async ( } if (tokens.length) { // Set aTokenAndRatesDeployer as temporal admin - addGas(await addressProvider.estimateGas.setPoolAdmin(atokenAndRatesDeployer.address)); await waitForTx(await addressProvider.setPoolAdmin(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); - const chunkedReserveFactors = chunk(reserveFactors, enableChunks); - const chunkedStableRatesEnabled = chunk(stableRatesEnabled, enableChunks); - - // TEST START const chunkedInputParams = chunk(inputParams, enableChunks); - // TEST END - - - console.log(`- Configure reserves in ${chunkedTokens.length} txs`); - for (let chunkIndex = 0; chunkIndex < chunkedTokens.length; chunkIndex++) { - // addGas(await atokenAndRatesDeployer.estimateGas.configureReserves( - // chunkedTokens[chunkIndex], - // chunkedBase[chunkIndex], - // chunkedliquidationThresholds[chunkIndex], - // chunkedliquidationBonuses[chunkIndex], - // chunkedReserveFactors[chunkIndex], - // chunkedStableRatesEnabled[chunkIndex], - // { gasLimit: 12000000 } - // )); - - - addGas(await atokenAndRatesDeployer.estimateGas.configureReserves( - chunkedInputParams[chunkIndex], - { gasLimit: 12000000 } - )); + console.log(`- Configure reserves in ${chunkedInputParams.length} txs`); + for (let chunkIndex = 0; chunkIndex < chunkedInputParams.length; chunkIndex++) { await waitForTx( await atokenAndRatesDeployer.configureReserves( chunkedInputParams[chunkIndex], @@ -498,7 +441,6 @@ export const configureReservesByHelper = async ( console.log(` - Init for: ${chunkedSymbols[chunkIndex].join(', ')}`); } // Set deployer back as admin - addGas(await addressProvider.estimateGas.setPoolAdmin(admin)); await waitForTx(await addressProvider.setPoolAdmin(admin)); } }; @@ -544,8 +486,28 @@ export const initTokenReservesByHelper = async ( let deployedVariableTokens: string[] = []; let deployedATokens: string[] = []; let deployedRates: string[] = []; + let reserveTokens: string[] = []; let reserveInitDecimals: string[] = []; let reserveSymbols: string[] = []; + + let initInputParams: { + aTokenImpl: string, + stableDebtTokenImpl: string, + variableDebtTokenImpl: string, + underlyingAssetDecimals: BigNumberish, + interestRateStrategyAddress: string, + underlyingAsset: string, + treasury: string, + incentivesController: string, + underlyingAssetName: string, + aTokenName: string, + aTokenSymbol: string, + variableDebtTokenName: string, + variableDebtTokenSymbol: string, + stableDebtTokenName: string, + stableDebtTokenSymbol: string, + }[] = []; + const network = process.env.MAINNET_FORK === 'true' ? eEthereumNetwork.main @@ -650,34 +612,47 @@ export const initTokenReservesByHelper = async ( deployedStableTokens.push(stableTokenImpl); deployedVariableTokens.push(variableTokenImpl); deployedATokens.push(aTokenImplementation); + reserveTokens.push(); deployedRates.push(strategyImpl); reserveInitDecimals.push(decimals.toString()); reserveSymbols.push(symbol); } - // Deploy init reserves per chunks - 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(reserveSymbols, initChunks); + for (let i = 0; i < deployedATokens.length; i ++) { + initInputParams.push({ + aTokenImpl: deployedATokens[i], + stableDebtTokenImpl: deployedStableTokens[i], + variableDebtTokenImpl: deployedVariableTokens[i], + underlyingAssetDecimals: reserveInitDecimals[i], + interestRateStrategyAddress: deployedRates[i], + underlyingAsset: tokenAddresses[reserveSymbols[i]], + treasury: treasuryAddress, + incentivesController: ZERO_ADDRESS, + underlyingAssetName: reserveSymbols[i], + aTokenName: `Aave interest bearing ${reserveSymbols[i]}`, + aTokenSymbol: `a${reserveSymbols[i]}`, + variableDebtTokenName: `Aave variable debt bearing ${reserveSymbols[i]}`, + variableDebtTokenSymbol: `variableDebt${reserveSymbols[i]}`, + stableDebtTokenName: `Aave stable debt bearing ${reserveSymbols[i]}`, + stableDebtTokenSymbol: `stableDebt${reserveSymbols[i]}` + }); + } - console.log(`- Reserves initialization in ${chunkedStableTokens.length} txs`); - for (let chunkIndex = 0; chunkIndex < chunkedDecimals.length; chunkIndex++) { + // Deploy init reserves per chunks + const chunkedSymbols = chunk(reserveSymbols, initChunks); + const chunkedInitInputParams = chunk(initInputParams, initChunks); + + const configurator = await getLendingPoolConfiguratorProxy(); + await waitForTx(await addressProvider.setPoolAdmin(admin)); + + console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`); + for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) { const tx3 = await waitForTx( - await atokenAndRatesDeployer.initReserve( - chunkedStableTokens[chunkIndex], - chunkedVariableTokens[chunkIndex], - chunkedAtokens[chunkIndex], - chunkedRates[chunkIndex], - chunkedDecimals[chunkIndex] - ) + await configurator.batchInitReserve(chunkedInitInputParams[chunkIndex]) ); console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`); console.log(' * gasUsed', tx3.gasUsed.toString()); - gasUsage = gasUsage.add(tx3.gasUsed); } // Set deployer back as admin diff --git a/helpers/oracles-helpers.ts b/helpers/oracles-helpers.ts index a1373b76..9fd2ba44 100644 --- a/helpers/oracles-helpers.ts +++ b/helpers/oracles-helpers.ts @@ -7,13 +7,12 @@ import { SymbolMap, } from './types'; -import {LendingRateOracle} from '../types/LendingRateOracle'; -import {PriceOracle} from '../types/PriceOracle'; -import {MockAggregator} from '../types/MockAggregator'; -import {deployMockAggregator} from './contracts-deployments'; -import {chunk, waitForTx} from './misc-utils'; -import {getStableAndVariableTokensHelper} from './contracts-getters'; -import { addGas } from './gas-tracker'; +import { LendingRateOracle } from '../types/LendingRateOracle'; +import { PriceOracle } from '../types/PriceOracle'; +import { MockAggregator } from '../types/MockAggregator'; +import { deployMockAggregator } from './contracts-deployments'; +import { chunk, waitForTx } from './misc-utils'; +import { getStableAndVariableTokensHelper } from './contracts-getters'; export const setInitialMarketRatesInRatesOracleByHelper = async ( marketRates: iMultiPoolsAssets, @@ -46,20 +45,12 @@ export const setInitialMarketRatesInRatesOracleByHelper = async ( const chunkedSymbols = chunk(symbols, ratesChunks); // Set helper as owner - addGas(await lendingRateOracleInstance.estimateGas.transferOwnership(stableAndVariableTokenHelper.address)); await waitForTx( await lendingRateOracleInstance.transferOwnership(stableAndVariableTokenHelper.address) ); console.log(`- Oracle borrow initalization in ${chunkedTokens.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedTokens.length; chunkIndex++) { - - addGas(await stableAndVariableTokenHelper.estimateGas.setOracleBorrowRates( - chunkedTokens[chunkIndex], - chunkedRates[chunkIndex], - lendingRateOracleInstance.address - )); - const tx3 = await waitForTx( await stableAndVariableTokenHelper.setOracleBorrowRates( chunkedTokens[chunkIndex], @@ -70,7 +61,6 @@ export const setInitialMarketRatesInRatesOracleByHelper = async ( console.log(` - Setted Oracle Borrow Rates for: ${chunkedSymbols[chunkIndex].join(', ')}`); } // Set back ownership - addGas(await stableAndVariableTokenHelper.estimateGas.setOracleOwnership(lendingRateOracleInstance.address, admin)); await waitForTx( await stableAndVariableTokenHelper.setOracleOwnership(lendingRateOracleInstance.address, admin) ); @@ -88,7 +78,6 @@ export const setInitialAssetPricesInOracle = async ( const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[ assetAddressIndex ]; - addGas(await priceOracleInstance.estimateGas.setAssetPrice(assetAddress, price)); await waitForTx(await priceOracleInstance.setAssetPrice(assetAddress, price)); } }; @@ -105,7 +94,6 @@ export const setAssetPricesInOracle = async ( const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[ assetAddressIndex ]; - addGas(await priceOracleInstance.estimateGas.setAssetPrice(assetAddress, price)); await waitForTx(await priceOracleInstance.setAssetPrice(assetAddress, price)); } }; From 89e93050769d1404ceda537a59e2174685b53ab5 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 5 Feb 2021 22:32:44 -0500 Subject: [PATCH 077/219] Updated test descriptions (sync) --- test/helpers/scenarios/borrow-negatives.json | 2 -- .../scenarios/borrow-repay-stable.json | 9 ++------ .../scenarios/borrow-repay-variable.json | 15 ------------ test/helpers/scenarios/credit-delegation.json | 2 +- test/helpers/scenarios/deposit.json | 5 ++-- .../scenarios/rebalance-stable-rate.json | 14 +++++------ .../scenarios/set-use-as-collateral.json | 11 +-------- test/helpers/scenarios/swap-rate-mode.json | 1 - .../helpers/scenarios/withdraw-negatives.json | 2 -- test/helpers/scenarios/withdraw.json | 23 +------------------ 10 files changed, 13 insertions(+), 71 deletions(-) diff --git a/test/helpers/scenarios/borrow-negatives.json b/test/helpers/scenarios/borrow-negatives.json index 6a8ceb66..03f4d005 100644 --- a/test/helpers/scenarios/borrow-negatives.json +++ b/test/helpers/scenarios/borrow-negatives.json @@ -52,7 +52,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "1" }, @@ -121,7 +120,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "1" }, diff --git a/test/helpers/scenarios/borrow-repay-stable.json b/test/helpers/scenarios/borrow-repay-stable.json index 3f472387..bdbf1aff 100644 --- a/test/helpers/scenarios/borrow-repay-stable.json +++ b/test/helpers/scenarios/borrow-repay-stable.json @@ -88,7 +88,7 @@ ] }, { - "description": "User 1 repays the half of the DAI borrow after one year", + "description": "User 1 repays half of the DAI borrow after one year", "actions": [ { "name": "mint", @@ -170,7 +170,7 @@ ] }, { - "description": "User 1 deposits 1000 DAI, user 2 tries to borrow 1000 DAI at a stable rate without any collateral (revert expected)", + "description": "User 1 deposits 1000 DAI, user 2 tries to borrow 1000 DAI at a stable rate without any collateral (revert expected) User 1 withdrawws", "actions": [ { "name": "mint", @@ -270,7 +270,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "1" }, @@ -308,7 +307,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "2" }, @@ -346,7 +344,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "3" }, @@ -384,7 +381,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "4" }, @@ -578,7 +574,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "2", "user": "1" }, diff --git a/test/helpers/scenarios/borrow-repay-variable.json b/test/helpers/scenarios/borrow-repay-variable.json index 46c17610..3c4ce368 100644 --- a/test/helpers/scenarios/borrow-repay-variable.json +++ b/test/helpers/scenarios/borrow-repay-variable.json @@ -83,7 +83,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "1" }, @@ -205,7 +204,6 @@ "name": "withdraw", "args": { "reserve": "WETH", - "amount": "-1", "user": "1" }, @@ -237,7 +235,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "0.001", "user": "2" }, @@ -269,7 +266,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "0" }, @@ -306,7 +302,6 @@ "name": "borrow", "args": { "reserve": "WETH", - "amount": "0.5", "borrowRateMode": "variable", "user": "1", @@ -340,7 +335,6 @@ "name": "repay", "args": { "reserve": "WETH", - "amount": "-1", "user": "2", "borrowRateMode": "variable", @@ -375,7 +369,6 @@ "name": "repay", "args": { "reserve": "WETH", - "amount": "0.2", "user": "3", "borrowRateMode": "variable", @@ -409,7 +402,6 @@ "name": "repay", "args": { "reserve": "WETH", - "amount": "-1", "borrowRateMode": "variable", "user": "1", @@ -426,7 +418,6 @@ "name": "withdraw", "args": { "reserve": "WETH", - "amount": "-1", "user": "0" }, @@ -530,7 +521,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "1" }, @@ -693,7 +683,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "0.1", "user": "3" }, @@ -719,7 +708,6 @@ "name": "withdraw", "args": { "reserve": "WETH", - "amount": "-1", "user": "3" }, @@ -793,7 +781,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "0.1", "user": "3" }, @@ -819,7 +806,6 @@ "name": "withdraw", "args": { "reserve": "WETH", - "amount": "-1", "user": "3" }, @@ -877,7 +863,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "2", "user": "6" }, diff --git a/test/helpers/scenarios/credit-delegation.json b/test/helpers/scenarios/credit-delegation.json index 0d15d7f1..2efabeb1 100644 --- a/test/helpers/scenarios/credit-delegation.json +++ b/test/helpers/scenarios/credit-delegation.json @@ -3,7 +3,7 @@ "description": "Test cases for the credit delegation related functions.", "stories": [ { - "description": "User 0 deposits 1000 DAI, user 0 delegates borrowing of 1 WETH on variable to user 4, user 4 borrows 1 WETH variable on behalf of user 0", + "description": "User 3 deposits 1000 WETH. User 0 deposits 1000 DAI, user 0 delegates borrowing of 1 WETH on variable to user 4, user 4 borrows 1 WETH variable on behalf of user 0", "actions": [ { "name": "mint", diff --git a/test/helpers/scenarios/deposit.json b/test/helpers/scenarios/deposit.json index 2456d931..b4b73879 100644 --- a/test/helpers/scenarios/deposit.json +++ b/test/helpers/scenarios/deposit.json @@ -34,7 +34,7 @@ ] }, { - "description": "User 1 deposits 1000 DAI after user 1", + "description": "User 1 deposits 1000 DAI after user 0", "actions": [ { "name": "mint", @@ -150,7 +150,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "0" }, @@ -191,7 +190,7 @@ ] }, { - "description": "User 1 deposits 0 ETH (revert expected)", + "description": "User 1 deposits 0 WETH (revert expected)", "actions": [ { "name": "mint", diff --git a/test/helpers/scenarios/rebalance-stable-rate.json b/test/helpers/scenarios/rebalance-stable-rate.json index 1da9a376..79c224f8 100644 --- a/test/helpers/scenarios/rebalance-stable-rate.json +++ b/test/helpers/scenarios/rebalance-stable-rate.json @@ -10,8 +10,7 @@ "args": { "reserve": "USDC", "user": "0", - "target": "1", - "borrowRateMode": "variable" + "target": "1" }, "expected": "revert", "revertMessage": "User does not have any stable rate loan for this reserve" @@ -19,7 +18,7 @@ ] }, { - "description": "User 0 deposits 1000 USDC, user 1 deposits 5 ETH, borrows 250 USDC at a stable rate, user 0 rebalances user 1 (revert expected)", + "description": "User 0 deposits 1000 USDC, user 1 deposits 7 WETH, borrows 250 USDC at a stable rate, user 0 rebalances user 1 (revert expected)", "actions": [ { "name": "mint", @@ -68,7 +67,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "7", "user": "1" }, @@ -97,7 +95,7 @@ ] }, { - "description": "User 1 borrows another 200 at stable, user 0 tries to rebalance but the conditions are not met (revert expected)", + "description": "User 1 borrows another 200 at variable, user 0 tries to rebalance but the conditions are not met (revert expected)", "actions": [ { "name": "borrow", @@ -122,7 +120,7 @@ ] }, { - "description": "User 1 borrows another 200 at stable, user 0 tries to rebalance but the conditions are not met (revert expected)", + "description": "User 1 borrows another 200 at variable, user 0 tries to rebalance but the conditions are not met (revert expected)", "actions": [ { "name": "borrow", @@ -147,7 +145,7 @@ ] }, { - "description": "User 1 borrows another 100 at stable, user 0 tries to rebalance but the conditions are not met (revert expected)", + "description": "User 1 borrows another 100 at variable, user 0 tries to rebalance but the conditions are not met (revert expected)", "actions": [ { "name": "borrow", @@ -173,7 +171,7 @@ }, { - "description": "User 0 borrows the remaining USDC (usage ratio = 100%). User 0 rebalances user 1", + "description": "User 1 borrows the remaining USDC (usage ratio = 100%) at variable. User 0 rebalances user 1", "actions": [ { "name": "borrow", diff --git a/test/helpers/scenarios/set-use-as-collateral.json b/test/helpers/scenarios/set-use-as-collateral.json index 53b5128e..2a206bb9 100644 --- a/test/helpers/scenarios/set-use-as-collateral.json +++ b/test/helpers/scenarios/set-use-as-collateral.json @@ -66,7 +66,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "2", "user": "1" }, @@ -76,7 +75,6 @@ "name": "setUseAsCollateral", "args": { "reserve": "WETH", - "user": "1", "useAsCollateral": "false" }, @@ -126,7 +124,6 @@ "name": "setUseAsCollateral", "args": { "reserve": "WETH", - "user": "1", "useAsCollateral": "false" }, @@ -136,7 +133,7 @@ ] }, { - "description": "User 1 Deposits 1000 AAVE, disables WETH as collateral. Should revert as 1000 AAVE are not enough to cover the debt (revert expected)", + "description": "User 1 Deposits 10 AAVE, disables WETH as collateral. Should revert as 10 AAVE are not enough to cover the debt (revert expected)", "actions": [ { "name": "mint", @@ -159,7 +156,6 @@ "name": "deposit", "args": { "reserve": "AAVE", - "amount": "10", "user": "1" }, @@ -169,7 +165,6 @@ "name": "setUseAsCollateral", "args": { "reserve": "WETH", - "user": "1", "useAsCollateral": "false" }, @@ -193,7 +188,6 @@ "name": "deposit", "args": { "reserve": "AAVE", - "amount": "640", "user": "1" }, @@ -203,7 +197,6 @@ "name": "setUseAsCollateral", "args": { "reserve": "WETH", - "user": "1", "useAsCollateral": "false" }, @@ -218,7 +211,6 @@ "name": "setUseAsCollateral", "args": { "reserve": "AAVE", - "user": "1", "useAsCollateral": "false" }, @@ -233,7 +225,6 @@ "name": "setUseAsCollateral", "args": { "reserve": "WETH", - "user": "1", "useAsCollateral": "true" }, diff --git a/test/helpers/scenarios/swap-rate-mode.json b/test/helpers/scenarios/swap-rate-mode.json index e2612586..e966af9a 100644 --- a/test/helpers/scenarios/swap-rate-mode.json +++ b/test/helpers/scenarios/swap-rate-mode.json @@ -82,7 +82,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "2", "user": "1" }, diff --git a/test/helpers/scenarios/withdraw-negatives.json b/test/helpers/scenarios/withdraw-negatives.json index 1fb070f5..fbc5c308 100644 --- a/test/helpers/scenarios/withdraw-negatives.json +++ b/test/helpers/scenarios/withdraw-negatives.json @@ -83,7 +83,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "1" }, @@ -103,7 +102,6 @@ "name": "withdraw", "args": { "reserve": "WETH", - "amount": "-1", "user": "1" }, diff --git a/test/helpers/scenarios/withdraw.json b/test/helpers/scenarios/withdraw.json index 436984fc..5f183eca 100644 --- a/test/helpers/scenarios/withdraw.json +++ b/test/helpers/scenarios/withdraw.json @@ -144,7 +144,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "0" }, @@ -153,13 +152,12 @@ ] }, { - "description": "User 0 withdraws half of the deposited ETH", + "description": "User 0 withdraws half of the deposited WETH", "actions": [ { "name": "withdraw", "args": { "reserve": "WETH", - "amount": "0.5", "user": "0" }, @@ -174,7 +172,6 @@ "name": "withdraw", "args": { "reserve": "WETH", - "amount": "-1", "user": "0" }, @@ -243,23 +240,6 @@ { "description": "Users 0 deposits 1000 DAI, user 1 Deposit 1000 USDC and 1 WETH, borrows 100 DAI. User 1 tries to withdraw all the USDC", "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "1" - }, - "expected": "success" - }, { "name": "deposit", "args": { @@ -316,7 +296,6 @@ "name": "deposit", "args": { "reserve": "WETH", - "amount": "1", "user": "1" }, From 01a662680f82c7241ec569b576160c2c6607b867 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Sat, 6 Feb 2021 22:10:29 -0500 Subject: [PATCH 078/219] Separated tests by market. Replace WETH9 symbol with 'UniWETH' to run test-lp. WIP. --- markets/aave/commons.ts | 3 +- markets/uniswap/commons.ts | 2 +- markets/uniswap/reservesConfigs.ts | 38 +- package.json | 41 +- test-suites/test-aave/__setup.spec.ts | 292 +++ .../addresses-provider-registry.spec.ts | 100 + .../test-aave/atoken-modifiers.spec.ts | 35 + test-suites/test-aave/atoken-permit.spec.ts | 312 +++ test-suites/test-aave/atoken-transfer.spec.ts | 99 + test-suites/test-aave/configurator.spec.ts | 386 ++++ .../test-aave/delegation-aware-atoken.spec.ts | 64 + test-suites/test-aave/flashloan.spec.ts | 497 +++++ test-suites/test-aave/helpers/actions.ts | 770 +++++++ test-suites/test-aave/helpers/almost-equal.ts | 31 + test-suites/test-aave/helpers/make-suite.ts | 191 ++ .../test-aave/helpers/scenario-engine.ts | 237 +++ .../helpers/scenarios/borrow-negatives.json | 142 ++ .../scenarios/borrow-repay-stable.json | 656 ++++++ .../scenarios/borrow-repay-variable.json | 945 +++++++++ .../helpers/scenarios/credit-delegation.json | 157 ++ .../test-aave/helpers/scenarios/deposit.json | 266 +++ .../scenarios/rebalance-stable-rate.json | 198 ++ .../scenarios/set-use-as-collateral.json | 236 +++ .../helpers/scenarios/swap-rate-mode.json | 167 ++ .../helpers/scenarios/withdraw-negatives.json | 114 + .../test-aave/helpers/scenarios/withdraw.json | 340 +++ .../test-aave/helpers/utils/calculations.ts | 1434 +++++++++++++ .../test-aave/helpers/utils/helpers.ts | 128 ++ .../helpers/utils/interfaces/index.ts | 40 + test-suites/test-aave/helpers/utils/math.ts | 97 + .../lending-pool-addresses-provider.spec.ts | 101 + .../test-aave/liquidation-atoken.spec.ts | 379 ++++ .../test-aave/liquidation-underlying.spec.ts | 492 +++++ .../test-aave/mainnet/check-list.spec.ts | 366 ++++ .../test-aave/pausable-functions.spec.ts | 330 +++ test-suites/test-aave/pool-modifiers.spec.ts | 241 +++ test-suites/test-aave/rate-strategy.spec.ts | 165 ++ test-suites/test-aave/scenario.spec.ts | 44 + .../test-aave/stable-rate-economy.spec.ts | 199 ++ test-suites/test-aave/stable-token.spec.ts | 37 + .../test-aave/subgraph-scenarios.spec.ts | 32 + .../test-aave/uniswapAdapters.base.spec.ts | 227 ++ .../uniswapAdapters.flashLiquidation.spec.ts | 850 ++++++++ .../uniswapAdapters.liquiditySwap.spec.ts | 1854 +++++++++++++++++ .../test-aave/uniswapAdapters.repay.spec.ts | 1469 +++++++++++++ test-suites/test-aave/upgradeability.spec.ts | 234 +++ .../test-aave/variable-debt-token.spec.ts | 36 + test-suites/test-aave/weth-gateway.spec.ts | 370 ++++ test-suites/test-lp/__setup.spec.ts | 292 +++ .../addresses-provider-registry.spec.ts | 100 + test-suites/test-lp/atoken-modifiers.spec.ts | 35 + test-suites/test-lp/atoken-permit.spec.ts | 312 +++ test-suites/test-lp/atoken-transfer.spec.ts | 99 + test-suites/test-lp/configurator.spec.ts | 386 ++++ .../test-lp/delegation-aware-atoken.spec.ts | 64 + test-suites/test-lp/flashloan.spec.ts | 497 +++++ test-suites/test-lp/helpers/actions.ts | 770 +++++++ test-suites/test-lp/helpers/almost-equal.ts | 31 + test-suites/test-lp/helpers/make-suite.ts | 191 ++ .../test-lp/helpers/scenario-engine.ts | 237 +++ .../helpers/scenarios/borrow-negatives.json | 142 ++ .../scenarios/borrow-repay-stable.json | 656 ++++++ .../scenarios/borrow-repay-variable.json | 945 +++++++++ .../helpers/scenarios/credit-delegation.json | 157 ++ .../test-lp/helpers/scenarios/deposit.json | 266 +++ .../scenarios/rebalance-stable-rate.json | 198 ++ .../scenarios/set-use-as-collateral.json | 236 +++ .../helpers/scenarios/swap-rate-mode.json | 167 ++ .../helpers/scenarios/withdraw-negatives.json | 114 + .../test-lp/helpers/scenarios/withdraw.json | 340 +++ .../test-lp/helpers/utils/calculations.ts | 1434 +++++++++++++ test-suites/test-lp/helpers/utils/helpers.ts | 129 ++ .../test-lp/helpers/utils/interfaces/index.ts | 40 + test-suites/test-lp/helpers/utils/math.ts | 97 + .../lending-pool-addresses-provider.spec.ts | 101 + .../test-lp/liquidation-atoken.spec.ts | 379 ++++ .../test-lp/liquidation-underlying.spec.ts | 492 +++++ .../test-lp/mainnet/check-list.spec.ts | 366 ++++ .../test-lp/pausable-functions.spec.ts | 330 +++ test-suites/test-lp/pool-modifiers.spec.ts | 241 +++ test-suites/test-lp/rate-strategy.spec.ts | 165 ++ test-suites/test-lp/scenario.spec.ts | 44 + .../test-lp/stable-rate-economy.spec.ts | 199 ++ test-suites/test-lp/stable-token.spec.ts | 37 + .../test-lp/subgraph-scenarios.spec.ts | 32 + .../test-lp/uniswapAdapters.base.spec.ts | 227 ++ .../uniswapAdapters.flashLiquidation.spec.ts | 850 ++++++++ .../uniswapAdapters.liquiditySwap.spec.ts | 1854 +++++++++++++++++ .../test-lp/uniswapAdapters.repay.spec.ts | 1469 +++++++++++++ test-suites/test-lp/upgradeability.spec.ts | 234 +++ .../test-lp/variable-debt-token.spec.ts | 36 + test-suites/test-lp/weth-gateway.spec.ts | 370 ++++ tsconfig.json | 2 +- 93 files changed, 30765 insertions(+), 42 deletions(-) create mode 100644 test-suites/test-aave/__setup.spec.ts create mode 100644 test-suites/test-aave/addresses-provider-registry.spec.ts create mode 100644 test-suites/test-aave/atoken-modifiers.spec.ts create mode 100644 test-suites/test-aave/atoken-permit.spec.ts create mode 100644 test-suites/test-aave/atoken-transfer.spec.ts create mode 100644 test-suites/test-aave/configurator.spec.ts create mode 100644 test-suites/test-aave/delegation-aware-atoken.spec.ts create mode 100644 test-suites/test-aave/flashloan.spec.ts create mode 100644 test-suites/test-aave/helpers/actions.ts create mode 100644 test-suites/test-aave/helpers/almost-equal.ts create mode 100644 test-suites/test-aave/helpers/make-suite.ts create mode 100644 test-suites/test-aave/helpers/scenario-engine.ts create mode 100644 test-suites/test-aave/helpers/scenarios/borrow-negatives.json create mode 100644 test-suites/test-aave/helpers/scenarios/borrow-repay-stable.json create mode 100644 test-suites/test-aave/helpers/scenarios/borrow-repay-variable.json create mode 100644 test-suites/test-aave/helpers/scenarios/credit-delegation.json create mode 100644 test-suites/test-aave/helpers/scenarios/deposit.json create mode 100644 test-suites/test-aave/helpers/scenarios/rebalance-stable-rate.json create mode 100644 test-suites/test-aave/helpers/scenarios/set-use-as-collateral.json create mode 100644 test-suites/test-aave/helpers/scenarios/swap-rate-mode.json create mode 100644 test-suites/test-aave/helpers/scenarios/withdraw-negatives.json create mode 100644 test-suites/test-aave/helpers/scenarios/withdraw.json create mode 100644 test-suites/test-aave/helpers/utils/calculations.ts create mode 100644 test-suites/test-aave/helpers/utils/helpers.ts create mode 100644 test-suites/test-aave/helpers/utils/interfaces/index.ts create mode 100644 test-suites/test-aave/helpers/utils/math.ts create mode 100644 test-suites/test-aave/lending-pool-addresses-provider.spec.ts create mode 100644 test-suites/test-aave/liquidation-atoken.spec.ts create mode 100644 test-suites/test-aave/liquidation-underlying.spec.ts create mode 100644 test-suites/test-aave/mainnet/check-list.spec.ts create mode 100644 test-suites/test-aave/pausable-functions.spec.ts create mode 100644 test-suites/test-aave/pool-modifiers.spec.ts create mode 100644 test-suites/test-aave/rate-strategy.spec.ts create mode 100644 test-suites/test-aave/scenario.spec.ts create mode 100644 test-suites/test-aave/stable-rate-economy.spec.ts create mode 100644 test-suites/test-aave/stable-token.spec.ts create mode 100644 test-suites/test-aave/subgraph-scenarios.spec.ts create mode 100644 test-suites/test-aave/uniswapAdapters.base.spec.ts create mode 100644 test-suites/test-aave/uniswapAdapters.flashLiquidation.spec.ts create mode 100644 test-suites/test-aave/uniswapAdapters.liquiditySwap.spec.ts create mode 100644 test-suites/test-aave/uniswapAdapters.repay.spec.ts create mode 100644 test-suites/test-aave/upgradeability.spec.ts create mode 100644 test-suites/test-aave/variable-debt-token.spec.ts create mode 100644 test-suites/test-aave/weth-gateway.spec.ts create mode 100644 test-suites/test-lp/__setup.spec.ts create mode 100644 test-suites/test-lp/addresses-provider-registry.spec.ts create mode 100644 test-suites/test-lp/atoken-modifiers.spec.ts create mode 100644 test-suites/test-lp/atoken-permit.spec.ts create mode 100644 test-suites/test-lp/atoken-transfer.spec.ts create mode 100644 test-suites/test-lp/configurator.spec.ts create mode 100644 test-suites/test-lp/delegation-aware-atoken.spec.ts create mode 100644 test-suites/test-lp/flashloan.spec.ts create mode 100644 test-suites/test-lp/helpers/actions.ts create mode 100644 test-suites/test-lp/helpers/almost-equal.ts create mode 100644 test-suites/test-lp/helpers/make-suite.ts create mode 100644 test-suites/test-lp/helpers/scenario-engine.ts create mode 100644 test-suites/test-lp/helpers/scenarios/borrow-negatives.json create mode 100644 test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json create mode 100644 test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json create mode 100644 test-suites/test-lp/helpers/scenarios/credit-delegation.json create mode 100644 test-suites/test-lp/helpers/scenarios/deposit.json create mode 100644 test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json create mode 100644 test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json create mode 100644 test-suites/test-lp/helpers/scenarios/swap-rate-mode.json create mode 100644 test-suites/test-lp/helpers/scenarios/withdraw-negatives.json create mode 100644 test-suites/test-lp/helpers/scenarios/withdraw.json create mode 100644 test-suites/test-lp/helpers/utils/calculations.ts create mode 100644 test-suites/test-lp/helpers/utils/helpers.ts create mode 100644 test-suites/test-lp/helpers/utils/interfaces/index.ts create mode 100644 test-suites/test-lp/helpers/utils/math.ts create mode 100644 test-suites/test-lp/lending-pool-addresses-provider.spec.ts create mode 100644 test-suites/test-lp/liquidation-atoken.spec.ts create mode 100644 test-suites/test-lp/liquidation-underlying.spec.ts create mode 100644 test-suites/test-lp/mainnet/check-list.spec.ts create mode 100644 test-suites/test-lp/pausable-functions.spec.ts create mode 100644 test-suites/test-lp/pool-modifiers.spec.ts create mode 100644 test-suites/test-lp/rate-strategy.spec.ts create mode 100644 test-suites/test-lp/scenario.spec.ts create mode 100644 test-suites/test-lp/stable-rate-economy.spec.ts create mode 100644 test-suites/test-lp/stable-token.spec.ts create mode 100644 test-suites/test-lp/subgraph-scenarios.spec.ts create mode 100644 test-suites/test-lp/uniswapAdapters.base.spec.ts create mode 100644 test-suites/test-lp/uniswapAdapters.flashLiquidation.spec.ts create mode 100644 test-suites/test-lp/uniswapAdapters.liquiditySwap.spec.ts create mode 100644 test-suites/test-lp/uniswapAdapters.repay.spec.ts create mode 100644 test-suites/test-lp/upgradeability.spec.ts create mode 100644 test-suites/test-lp/variable-debt-token.spec.ts create mode 100644 test-suites/test-lp/weth-gateway.spec.ts diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index dc9bce99..be9ae7e5 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -34,7 +34,7 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniLINKWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), @@ -44,6 +44,7 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; + // ---------------- // PROTOCOL GLOBAL PARAMS // ---------------- diff --git a/markets/uniswap/commons.ts b/markets/uniswap/commons.ts index fda18c55..a74338bc 100644 --- a/markets/uniswap/commons.ts +++ b/markets/uniswap/commons.ts @@ -34,7 +34,7 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniLINKWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), diff --git a/markets/uniswap/reservesConfigs.ts b/markets/uniswap/reservesConfigs.ts index 6961d4d5..6e1e14a1 100644 --- a/markets/uniswap/reservesConfigs.ts +++ b/markets/uniswap/reservesConfigs.ts @@ -13,7 +13,7 @@ export const strategyWETH: IReserveParams = { liquidationThreshold: '8250', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -30,7 +30,7 @@ export const strategyWBTC: IReserveParams = { liquidationThreshold: '7500', liquidationBonus: '11000', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '8', aTokenImpl: eContractid.AToken, reserveFactor: '2000' @@ -47,7 +47,7 @@ export const strategyDAI: IReserveParams = { liquidationThreshold: '8000', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -64,7 +64,7 @@ export const strategyUSDC: IReserveParams = { liquidationThreshold: '8500', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '6', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -81,7 +81,7 @@ export const strategyUSDT: IReserveParams = { liquidationThreshold: '8500', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '6', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -98,7 +98,7 @@ export const strategyDAIWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '500' @@ -115,7 +115,7 @@ export const strategyWBTCWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -132,7 +132,7 @@ export const strategyAAVEWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '500' @@ -149,7 +149,7 @@ export const strategyBATWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -166,7 +166,7 @@ export const strategyUSDCDAI: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -183,7 +183,7 @@ export const strategyCRVWETH: IReserveParams = { liquidationThreshold: '6000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '500' @@ -200,7 +200,7 @@ export const strategyLINKWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -217,7 +217,7 @@ export const strategyMKRWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -234,7 +234,7 @@ export const strategyRENWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -251,7 +251,7 @@ export const strategySNXWETH: IReserveParams = { liquidationThreshold: '6000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000' @@ -268,7 +268,7 @@ export const strategyUNIWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -285,7 +285,7 @@ export const strategyUSDCWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -302,7 +302,7 @@ export const strategyWBTCUSDC: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -319,7 +319,7 @@ export const strategyYFIWETH: IReserveParams = { liquidationThreshold: '6000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: false, + stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' diff --git a/package.json b/package.json index 321501ee..41430a28 100644 --- a/package.json +++ b/package.json @@ -16,23 +16,24 @@ "hardhat:docker": "hardhat --network hardhatevm_docker", "compile": "SKIP_LOAD=true hardhat compile", "console:fork": "MAINNET_FORK=true hardhat console", - "test": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test/*.spec.ts", - "test-scenarios": "npx hardhat test test/__setup.spec.ts test/scenario.spec.ts", - "test-repay-with-collateral": "hardhat test test/__setup.spec.ts test/repay-with-collateral.spec.ts", - "test-liquidate-with-collateral": "hardhat test test/__setup.spec.ts test/flash-liquidation-with-collateral.spec.ts", - "test-liquidate-underlying": "hardhat test test/__setup.spec.ts test/liquidation-underlying.spec.ts", - "test-configurator": "hardhat test test/__setup.spec.ts test/configurator.spec.ts", - "test-transfers": "hardhat test test/__setup.spec.ts test/atoken-transfer.spec.ts", - "test-flash": "hardhat test test/__setup.spec.ts test/flashloan.spec.ts", - "test-liquidate": "hardhat test test/__setup.spec.ts test/liquidation-atoken.spec.ts", - "test-deploy": "hardhat test test/__setup.spec.ts test/test-init.spec.ts", - "test-pausable": "hardhat test test/__setup.spec.ts test/pausable-functions.spec.ts", - "test-permit": "hardhat test test/__setup.spec.ts test/atoken-permit.spec.ts", - "test-stable-and-atokens": "hardhat test test/__setup.spec.ts test/atoken-transfer.spec.ts test/stable-token.spec.ts", - "test-subgraph:scenarios": "hardhat --network hardhatevm_docker test test/__setup.spec.ts test/subgraph-scenarios.spec.ts", - "test-weth": "hardhat test test/__setup.spec.ts test/weth-gateway.spec.ts", - "test-uniswap": "hardhat test test/__setup.spec.ts test/uniswapAdapters*.spec.ts", - "test:main:check-list": "MAINNET_FORK=true TS_NODE_TRANSPILE_ONLY=1 hardhat test test/__setup.spec.ts test/mainnet/check-list.spec.ts", + "test": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-aave/*.spec.ts", + "test-lp": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-lp/*.spec.ts", + "test-scenarios": "npx hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/scenario.spec.ts", + "test-repay-with-collateral": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/repay-with-collateral.spec.ts", + "test-liquidate-with-collateral": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/flash-liquidation-with-collateral.spec.ts", + "test-liquidate-underlying": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/liquidation-underlying.spec.ts", + "test-configurator": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/configurator.spec.ts", + "test-transfers": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-transfer.spec.ts", + "test-flash": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/flashloan.spec.ts", + "test-liquidate": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/liquidation-atoken.spec.ts", + "test-deploy": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/test-init.spec.ts", + "test-pausable": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/pausable-functions.spec.ts", + "test-permit": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-permit.spec.ts", + "test-stable-and-atokens": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-transfer.spec.ts test-suites/test-aave/stable-token.spec.ts", + "test-subgraph:scenarios": "hardhat --network hardhatevm_docker test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/subgraph-scenarios.spec.ts", + "test-weth": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/weth-gateway.spec.ts", + "test-uniswap": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/uniswapAdapters*.spec.ts", + "test:main:check-list": "MAINNET_FORK=true TS_NODE_TRANSPILE_ONLY=1 hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/mainnet/check-list.spec.ts", "dev:coverage": "buidler compile --force && buidler coverage --network coverage", "aave:evm:dev:migration": "npm run compile && hardhat aave:dev", "aave:docker:full:migration": "npm run compile && npm run hardhat:docker -- aave:mainnet", @@ -45,8 +46,8 @@ "uniswap:fork:main": "npm run compile && MAINNET_FORK=true hardhat uniswap:mainnet", "aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify", "aave:main:full:initialize": "npm run compile && MAINNET_FORK=true full:initialize-tokens --pool Aave", - "prettier:check": "npx prettier -c 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test/**/*.ts'", - "prettier:write": "prettier --write 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test/**/*.ts'", + "prettier:check": "npx prettier -c 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test-suites/test-aave/**/*.ts'", + "prettier:write": "prettier --write 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test-suites/test-aave/**/*.ts'", "ci:test": "npm run compile && npm run test", "ci:clean": "rm -rf ./artifacts ./cache ./types", "print-contracts:kovan": "npm run hardhat:kovan -- print-contracts", @@ -121,7 +122,7 @@ }, "husky": { "hooks": { - "pre-commit": "pretty-quick --staged --pattern 'contracts/**/*.sol' --pattern 'helpers/**/*.ts' --pattern 'test/**/*.ts' --pattern 'tasks/**/*.ts'" + "pre-commit": "pretty-quick --staged --pattern 'contracts/**/*.sol' --pattern 'helpers/**/*.ts' --pattern 'test-suites/test-aave/**/*.ts' --pattern 'tasks/**/*.ts'" } }, "author": "Aave", diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts new file mode 100644 index 00000000..c099facd --- /dev/null +++ b/test-suites/test-aave/__setup.spec.ts @@ -0,0 +1,292 @@ +import rawBRE from 'hardhat'; +import { MockContract } from 'ethereum-waffle'; +import { + insertContractAddressInDb, + getEthersSigners, + registerContractInJsonDb, +} from '../../helpers/contracts-helpers'; +import { + deployLendingPoolAddressesProvider, + deployMintableERC20, + deployLendingPoolAddressesProviderRegistry, + deployLendingPoolConfigurator, + deployLendingPool, + deployPriceOracle, + deployAaveOracle, + deployLendingPoolCollateralManager, + deployMockFlashLoanReceiver, + deployWalletBalancerProvider, + deployAaveProtocolDataProvider, + deployLendingRateOracle, + deployStableAndVariableTokensHelper, + deployATokensAndRatesHelper, + deployWETHGateway, + deployWETHMocked, + deployMockUniswapRouter, + deployUniswapLiquiditySwapAdapter, + deployUniswapRepayAdapter, + deployFlashLiquidationAdapter, +} from '../../helpers/contracts-deployments'; +import { Signer } from 'ethers'; +import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types'; +import { MintableERC20 } from '../../types/MintableERC20'; +import { + ConfigNames, + getReservesConfigByPool, + getTreasuryAddress, + loadPoolConfig, +} from '../../helpers/configuration'; +import { initializeMakeSuite } from './helpers/make-suite'; + +import { + setInitialAssetPricesInOracle, + deployAllMockAggregators, + setInitialMarketRatesInRatesOracleByHelper, +} from '../../helpers/oracles-helpers'; +import { DRE, waitForTx } from '../../helpers/misc-utils'; +import { initReservesByHelper, configureReservesByHelper } from '../../helpers/init-helpers'; +import AaveConfig from '../../markets/aave'; +import { ZERO_ADDRESS } from '../../helpers/constants'; +import { + getLendingPool, + getLendingPoolConfiguratorProxy, + getPairsTokenAggregator, +} from '../../helpers/contracts-getters'; +import { WETH9Mocked } from '../../types/WETH9Mocked'; + +const MOCK_USD_PRICE_IN_WEI = AaveConfig.ProtocolGlobalParams.MockUsdPriceInWei; +const ALL_ASSETS_INITIAL_PRICES = AaveConfig.Mocks.AllAssetsInitialPrices; +const USD_ADDRESS = AaveConfig.ProtocolGlobalParams.UsdAddress; +const MOCK_CHAINLINK_AGGREGATORS_PRICES = AaveConfig.Mocks.AllAssetsInitialPrices; +const LENDING_RATE_ORACLE_RATES_COMMON = AaveConfig.LendingRateOracleRatesCommon; + +const deployAllMockTokens = async (deployer: Signer) => { + const tokens: { [symbol: string]: MockContract | MintableERC20 | WETH9Mocked } = {}; + + const protoConfigData = getReservesConfigByPool(AavePools.proto); + + for (const tokenSymbol of Object.keys(TokenContractId)) { + if (tokenSymbol === 'WETH') { + tokens[tokenSymbol] = await deployWETHMocked(); + await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); + continue; + } + let decimals = 18; + + let configData = (protoConfigData)[tokenSymbol]; + + if (!configData) { + decimals = 18; + } + + tokens[tokenSymbol] = await deployMintableERC20([ + tokenSymbol, + tokenSymbol, + configData ? configData.reserveDecimals : 18, + ]); + await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); + } + + return tokens; +}; + +const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { + console.time('setup'); + const aaveAdmin = await deployer.getAddress(); + + const mockTokens = await deployAllMockTokens(deployer); + + const addressesProvider = await deployLendingPoolAddressesProvider(AaveConfig.MarketId); + await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin)); + + //setting users[1] as emergency admin, which is in position 2 in the DRE addresses list + const addressList = await Promise.all( + (await DRE.ethers.getSigners()).map((signer) => signer.getAddress()) + ); + + await waitForTx(await addressesProvider.setEmergencyAdmin(addressList[2])); + + const addressesProviderRegistry = await deployLendingPoolAddressesProviderRegistry(); + await waitForTx( + await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 1) + ); + + const lendingPoolImpl = await deployLendingPool(); + + await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address)); + + const lendingPoolAddress = await addressesProvider.getLendingPool(); + const lendingPoolProxy = await getLendingPool(lendingPoolAddress); + + await insertContractAddressInDb(eContractid.LendingPool, lendingPoolProxy.address); + + const lendingPoolConfiguratorImpl = await deployLendingPoolConfigurator(); + await waitForTx( + await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImpl.address) + ); + const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy( + await addressesProvider.getLendingPoolConfigurator() + ); + await insertContractAddressInDb( + eContractid.LendingPoolConfigurator, + 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( + ALL_ASSETS_INITIAL_PRICES, + { + WETH: mockTokens.WETH.address, + DAI: mockTokens.DAI.address, + TUSD: mockTokens.TUSD.address, + USDC: mockTokens.USDC.address, + USDT: mockTokens.USDT.address, + SUSD: mockTokens.SUSD.address, + AAVE: mockTokens.AAVE.address, + BAT: mockTokens.BAT.address, + MKR: mockTokens.MKR.address, + LINK: mockTokens.LINK.address, + KNC: mockTokens.KNC.address, + WBTC: mockTokens.WBTC.address, + MANA: mockTokens.MANA.address, + ZRX: mockTokens.ZRX.address, + SNX: mockTokens.SNX.address, + BUSD: mockTokens.BUSD.address, + YFI: mockTokens.BUSD.address, + REN: mockTokens.REN.address, + UNI: mockTokens.UNI.address, + ENJ: mockTokens.ENJ.address, + UniDAI: mockTokens.UniDAI.address, + UniUSDC: mockTokens.UniUSDC.address, + UniUSDT: mockTokens.UniUSDT.address, + UniWBTC: mockTokens.UniWBTC.address, + UniWETH: mockTokens.UniWETH.address, + UniDAIWETH: mockTokens.UniDAIWETH.address, + UniWBTCWETH: mockTokens.UniWBTCWETH.address, + UniAAVEWETH: mockTokens.UniAAVEWETH.address, + UniBATWETH: mockTokens.UniBATWETH.address, + UniUSDCDAI: mockTokens.UniUSDCDAI.address, + UniCRVWETH: mockTokens.UniCRVWETH.address, + UniLINKWETH: mockTokens.UniLINKWETH.address, + UniMKRWETH: mockTokens.UniMKRWETH.address, + UniRENWETH: mockTokens.UniRENWETH.address, + UniSNXWETH: mockTokens.UniSNXWETH.address, + UniUNIWETH: mockTokens.UniUNIWETH.address, + UniUSDCWETH: mockTokens.UniUSDCWETH.address, + UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, + UniYFIWETH: mockTokens.UniYFIWETH.address, + USD: USD_ADDRESS, + }, + fallbackOracle + ); + + const mockAggregators = await deployAllMockAggregators(MOCK_CHAINLINK_AGGREGATORS_PRICES); + + const allTokenAddresses = Object.entries(mockTokens).reduce( + (accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, tokenContract]) => ({ + ...accum, + [tokenSymbol]: tokenContract.address, + }), + {} + ); + const allAggregatorsAddresses = Object.entries(mockAggregators).reduce( + (accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, aggregator]) => ({ + ...accum, + [tokenSymbol]: aggregator.address, + }), + {} + ); + + const [tokens, aggregators] = getPairsTokenAggregator(allTokenAddresses, allAggregatorsAddresses); + + await deployAaveOracle([tokens, aggregators, fallbackOracle.address, mockTokens.WETH.address]); + await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address)); + + const lendingRateOracle = await deployLendingRateOracle(); + await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); + + const { USD, ...tokensAddressesWithoutUsd } = allTokenAddresses; + const allReservesAddresses = { + ...tokensAddressesWithoutUsd, + }; + await setInitialMarketRatesInRatesOracleByHelper( + LENDING_RATE_ORACLE_RATES_COMMON, + allReservesAddresses, + lendingRateOracle, + aaveAdmin + ); + + const reservesParams = getReservesConfigByPool(AavePools.proto); + + const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address); + + await insertContractAddressInDb(eContractid.AaveProtocolDataProvider, testHelpers.address); + const admin = await deployer.getAddress(); + + console.log('Initialize configuration'); + + const config = loadPoolConfig(ConfigNames.Aave); + + const treasuryAddress = await getTreasuryAddress(config); + + await initReservesByHelper( + reservesParams, + allReservesAddresses, + admin, + treasuryAddress, + ZERO_ADDRESS, + false + ); + await configureReservesByHelper(reservesParams, allReservesAddresses, testHelpers, admin); + + const collateralManager = await deployLendingPoolCollateralManager(); + await waitForTx( + await addressesProvider.setLendingPoolCollateralManager(collateralManager.address) + ); + await deployMockFlashLoanReceiver(addressesProvider.address); + + const mockUniswapRouter = await deployMockUniswapRouter(); + + const adapterParams: [string, string, string] = [ + addressesProvider.address, + mockUniswapRouter.address, + mockTokens.WETH.address, + ]; + + await deployUniswapLiquiditySwapAdapter(adapterParams); + await deployUniswapRepayAdapter(adapterParams); + await deployFlashLiquidationAdapter(adapterParams); + + await deployWalletBalancerProvider(); + + await deployWETHGateway([mockTokens.WETH.address, lendingPoolAddress]); + + console.timeEnd('setup'); +}; + +before(async () => { + await rawBRE.run('set-DRE'); + const [deployer, secondaryWallet] = await getEthersSigners(); + const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; + + if (MAINNET_FORK) { + await rawBRE.run('aave:mainnet'); + } else { + console.log('-> Deploying test environment...'); + await buildTestEnv(deployer, secondaryWallet); + } + + await initializeMakeSuite(); + console.log('\n***************'); + console.log('Setup and snapshot finished'); + console.log('***************\n'); +}); diff --git a/test-suites/test-aave/addresses-provider-registry.spec.ts b/test-suites/test-aave/addresses-provider-registry.spec.ts new file mode 100644 index 00000000..77198278 --- /dev/null +++ b/test-suites/test-aave/addresses-provider-registry.spec.ts @@ -0,0 +1,100 @@ +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { ZERO_ADDRESS } from '../../helpers/constants'; +import { ProtocolErrors } from '../../helpers/types'; + +const { expect } = require('chai'); + +makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => { + it('Checks the addresses provider is added to the registry', async () => { + const { addressesProvider, registry } = testEnv; + + const providers = await registry.getAddressesProvidersList(); + + expect(providers.length).to.be.equal(1, 'Invalid length of the addresses providers list'); + expect(providers[0].toString()).to.be.equal( + addressesProvider.address, + ' Invalid addresses provider added to the list' + ); + }); + + it('tries to register an addresses provider with id 0', async () => { + const { users, registry } = testEnv; + const { LPAPR_INVALID_ADDRESSES_PROVIDER_ID } = ProtocolErrors; + + await expect(registry.registerAddressesProvider(users[2].address, '0')).to.be.revertedWith( + LPAPR_INVALID_ADDRESSES_PROVIDER_ID + ); + }); + + it('Registers a new mock addresses provider', async () => { + const { users, registry } = testEnv; + + //simulating an addresses provider using the users[1] wallet address + await registry.registerAddressesProvider(users[1].address, '2'); + + const providers = await registry.getAddressesProvidersList(); + + expect(providers.length).to.be.equal(2, 'Invalid length of the addresses providers list'); + expect(providers[1].toString()).to.be.equal( + users[1].address, + ' Invalid addresses provider added to the list' + ); + }); + + it('Removes the mock addresses provider', async () => { + const { users, registry, addressesProvider } = testEnv; + + const id = await registry.getAddressesProviderIdByAddress(users[1].address); + + expect(id).to.be.equal('2', 'Invalid isRegistered return value'); + + await registry.unregisterAddressesProvider(users[1].address); + + const providers = await registry.getAddressesProvidersList(); + + expect(providers.length).to.be.equal(2, 'Invalid length of the addresses providers list'); + expect(providers[0].toString()).to.be.equal( + addressesProvider.address, + ' Invalid addresses provider added to the list' + ); + expect(providers[1].toString()).to.be.equal(ZERO_ADDRESS, ' Invalid addresses'); + }); + + it('Tries to remove a unregistered addressesProvider', async () => { + const { LPAPR_PROVIDER_NOT_REGISTERED } = ProtocolErrors; + + const { users, registry } = testEnv; + + await expect(registry.unregisterAddressesProvider(users[2].address)).to.be.revertedWith( + LPAPR_PROVIDER_NOT_REGISTERED + ); + }); + + it('Tries to remove a unregistered addressesProvider', async () => { + const { LPAPR_PROVIDER_NOT_REGISTERED } = ProtocolErrors; + + const { users, registry } = testEnv; + + await expect(registry.unregisterAddressesProvider(users[2].address)).to.be.revertedWith( + LPAPR_PROVIDER_NOT_REGISTERED + ); + }); + + it('Tries to add an already added addressesProvider with a different id. Should overwrite the previous id', async () => { + const { users, registry, addressesProvider } = testEnv; + + await registry.registerAddressesProvider(addressesProvider.address, '2'); + + const providers = await registry.getAddressesProvidersList(); + + const id = await registry.getAddressesProviderIdByAddress(addressesProvider.address); + + expect(providers.length).to.be.equal(2, 'Invalid length of the addresses providers list'); + + expect(providers[0].toString()).to.be.equal( + addressesProvider.address, + ' Invalid addresses provider added to the list' + ); + expect(providers[1].toString()).to.be.equal(ZERO_ADDRESS, ' Invalid addresses'); + }); +}); diff --git a/test-suites/test-aave/atoken-modifiers.spec.ts b/test-suites/test-aave/atoken-modifiers.spec.ts new file mode 100644 index 00000000..f1ae1199 --- /dev/null +++ b/test-suites/test-aave/atoken-modifiers.spec.ts @@ -0,0 +1,35 @@ +import { expect } from 'chai'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors } from '../../helpers/types'; + +makeSuite('AToken: Modifiers', (testEnv: TestEnv) => { + const { CT_CALLER_MUST_BE_LENDING_POOL } = ProtocolErrors; + + it('Tries to invoke mint not being the LendingPool', async () => { + const { deployer, aDai } = testEnv; + await expect(aDai.mint(deployer.address, '1', '1')).to.be.revertedWith( + CT_CALLER_MUST_BE_LENDING_POOL + ); + }); + + it('Tries to invoke burn not being the LendingPool', async () => { + const { deployer, aDai } = testEnv; + await expect(aDai.burn(deployer.address, deployer.address, '1', '1')).to.be.revertedWith( + CT_CALLER_MUST_BE_LENDING_POOL + ); + }); + + it('Tries to invoke transferOnLiquidation not being the LendingPool', async () => { + const { deployer, users, aDai } = testEnv; + await expect( + aDai.transferOnLiquidation(deployer.address, users[0].address, '1') + ).to.be.revertedWith(CT_CALLER_MUST_BE_LENDING_POOL); + }); + + it('Tries to invoke transferUnderlyingTo not being the LendingPool', async () => { + const { deployer, aDai } = testEnv; + await expect(aDai.transferUnderlyingTo(deployer.address, '1')).to.be.revertedWith( + CT_CALLER_MUST_BE_LENDING_POOL + ); + }); +}); diff --git a/test-suites/test-aave/atoken-permit.spec.ts b/test-suites/test-aave/atoken-permit.spec.ts new file mode 100644 index 00000000..24e8b39c --- /dev/null +++ b/test-suites/test-aave/atoken-permit.spec.ts @@ -0,0 +1,312 @@ +import { MAX_UINT_AMOUNT, ZERO_ADDRESS } from '../../helpers/constants'; +import { BUIDLEREVM_CHAINID } from '../../helpers/buidler-constants'; +import { buildPermitParams, getSignatureFromTypedData } from '../../helpers/contracts-helpers'; +import { expect } from 'chai'; +import { ethers } from 'ethers'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { DRE } from '../../helpers/misc-utils'; +import { waitForTx } from '../../helpers/misc-utils'; +import { _TypedDataEncoder } from 'ethers/lib/utils'; + +const { parseEther } = ethers.utils; + +makeSuite('AToken: Permit', (testEnv: TestEnv) => { + it('Checks the domain separator', async () => { + const { aDai } = testEnv; + const separator = await aDai.DOMAIN_SEPARATOR(); + + const domain = { + name: await aDai.name(), + version: '1', + chainId: DRE.network.config.chainId, + verifyingContract: aDai.address, + }; + const domainSeparator = _TypedDataEncoder.hashDomain(domain); + + expect(separator).to.be.equal(domainSeparator, 'Invalid domain separator'); + }); + + it('Get aDAI for tests', async () => { + const { dai, pool, deployer } = testEnv; + + await dai.mint(parseEther('20000')); + await dai.approve(pool.address, parseEther('20000')); + + await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); + }); + + it('Reverts submitting a permit with 0 expiration', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const tokenName = await aDai.name(); + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const expiration = 0; + const nonce = (await aDai._nonces(owner.address)).toNumber(); + const permitAmount = ethers.utils.parseEther('2').toString(); + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + tokenName, + owner.address, + spender.address, + nonce, + permitAmount, + expiration.toFixed() + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( + '0', + 'INVALID_ALLOWANCE_BEFORE_PERMIT' + ); + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await expect( + aDai + .connect(spender.signer) + .permit(owner.address, spender.address, permitAmount, expiration, v, r, s) + ).to.be.revertedWith('INVALID_EXPIRATION'); + + expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( + '0', + 'INVALID_ALLOWANCE_AFTER_PERMIT' + ); + }); + + it('Submits a permit with maximum expiration length', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = (await aDai._nonces(owner.address)).toNumber(); + const permitAmount = parseEther('2').toString(); + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + await aDai.name(), + owner.address, + spender.address, + nonce, + deadline, + permitAmount + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( + '0', + 'INVALID_ALLOWANCE_BEFORE_PERMIT' + ); + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await waitForTx( + await aDai + .connect(spender.signer) + .permit(owner.address, spender.address, permitAmount, deadline, v, r, s) + ); + + expect((await aDai._nonces(owner.address)).toNumber()).to.be.equal(1); + }); + + it('Cancels the previous permit', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = (await aDai._nonces(owner.address)).toNumber(); + const permitAmount = '0'; + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + await aDai.name(), + owner.address, + spender.address, + nonce, + deadline, + permitAmount + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( + ethers.utils.parseEther('2'), + 'INVALID_ALLOWANCE_BEFORE_PERMIT' + ); + + await waitForTx( + await aDai + .connect(spender.signer) + .permit(owner.address, spender.address, permitAmount, deadline, v, r, s) + ); + expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( + permitAmount, + 'INVALID_ALLOWANCE_AFTER_PERMIT' + ); + + expect((await aDai._nonces(owner.address)).toNumber()).to.be.equal(2); + }); + + it('Tries to submit a permit with invalid nonce', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = 1000; + const permitAmount = '0'; + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + await aDai.name(), + owner.address, + spender.address, + nonce, + deadline, + permitAmount + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await expect( + aDai + .connect(spender.signer) + .permit(owner.address, spender.address, permitAmount, deadline, v, r, s) + ).to.be.revertedWith('INVALID_SIGNATURE'); + }); + + it('Tries to submit a permit with invalid expiration (previous to the current block)', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const expiration = '1'; + const nonce = (await aDai._nonces(owner.address)).toNumber(); + const permitAmount = '0'; + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + await aDai.name(), + owner.address, + spender.address, + nonce, + expiration, + permitAmount + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await expect( + aDai + .connect(spender.signer) + .permit(owner.address, spender.address, expiration, permitAmount, v, r, s) + ).to.be.revertedWith('INVALID_EXPIRATION'); + }); + + it('Tries to submit a permit with invalid signature', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = (await aDai._nonces(owner.address)).toNumber(); + const permitAmount = '0'; + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + await aDai.name(), + owner.address, + spender.address, + nonce, + deadline, + permitAmount + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await expect( + aDai + .connect(spender.signer) + .permit(owner.address, ZERO_ADDRESS, permitAmount, deadline, v, r, s) + ).to.be.revertedWith('INVALID_SIGNATURE'); + }); + + it('Tries to submit a permit with invalid owner', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const expiration = MAX_UINT_AMOUNT; + const nonce = (await aDai._nonces(owner.address)).toNumber(); + const permitAmount = '0'; + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + await aDai.name(), + owner.address, + spender.address, + nonce, + expiration, + permitAmount + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await expect( + aDai + .connect(spender.signer) + .permit(ZERO_ADDRESS, spender.address, expiration, permitAmount, v, r, s) + ).to.be.revertedWith('INVALID_OWNER'); + }); +}); diff --git a/test-suites/test-aave/atoken-transfer.spec.ts b/test-suites/test-aave/atoken-transfer.spec.ts new file mode 100644 index 00000000..c6451280 --- /dev/null +++ b/test-suites/test-aave/atoken-transfer.spec.ts @@ -0,0 +1,99 @@ +import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, ZERO_ADDRESS } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { expect } from 'chai'; +import { ethers } from 'ethers'; +import { RateMode, ProtocolErrors } from '../../helpers/types'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { CommonsConfig } from '../../markets/aave/commons'; + +const AAVE_REFERRAL = CommonsConfig.ProtocolGlobalParams.AaveReferral; + +makeSuite('AToken: Transfer', (testEnv: TestEnv) => { + const { + INVALID_FROM_BALANCE_AFTER_TRANSFER, + INVALID_TO_BALANCE_AFTER_TRANSFER, + VL_TRANSFER_NOT_ALLOWED, + } = ProtocolErrors; + + it('User 0 deposits 1000 DAI, transfers to user 1', async () => { + const { users, pool, dai, aDai } = testEnv; + + await dai.connect(users[0].signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 1 deposits 1000 DAI + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool + .connect(users[0].signer) + .deposit(dai.address, amountDAItoDeposit, users[0].address, '0'); + + 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); + + expect(fromBalance.toString()).to.be.equal('0', INVALID_FROM_BALANCE_AFTER_TRANSFER); + expect(toBalance.toString()).to.be.equal( + amountDAItoDeposit.toString(), + INVALID_TO_BALANCE_AFTER_TRANSFER + ); + }); + + 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')); + + await weth.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(users[0].signer) + .deposit(weth.address, ethers.utils.parseEther('1.0'), userAddress, '0'); + await pool + .connect(users[1].signer) + .borrow( + weth.address, + ethers.utils.parseEther('0.1'), + RateMode.Stable, + AAVE_REFERRAL, + 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), + VL_TRANSFER_NOT_ALLOWED + ).to.be.revertedWith(VL_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()); + }); +}); diff --git a/test-suites/test-aave/configurator.spec.ts b/test-suites/test-aave/configurator.spec.ts new file mode 100644 index 00000000..c94dcdf8 --- /dev/null +++ b/test-suites/test-aave/configurator.spec.ts @@ -0,0 +1,386 @@ +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { APPROVAL_AMOUNT_LENDING_POOL, RAY } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { ProtocolErrors } from '../../helpers/types'; +import { strategyWETH } from '../../markets/aave/reservesConfigs'; + +const { expect } = require('chai'); + +makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { + const { + CALLER_NOT_POOL_ADMIN, + LPC_RESERVE_LIQUIDITY_NOT_0, + RC_INVALID_LTV, + RC_INVALID_LIQ_THRESHOLD, + RC_INVALID_LIQ_BONUS, + RC_INVALID_DECIMALS, + RC_INVALID_RESERVE_FACTOR, + } = ProtocolErrors; + + 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(RC_INVALID_RESERVE_FACTOR); + }); + + it('Deactivates the ETH reserve', async () => { + const { configurator, weth, helpersContract } = testEnv; + await configurator.deactivateReserve(weth.address); + const { isActive } = await helpersContract.getReserveConfigurationData(weth.address); + expect(isActive).to.be.equal(false); + }); + + it('Rectivates the ETH reserve', async () => { + const { configurator, weth, helpersContract } = testEnv; + await configurator.activateReserve(weth.address); + + const { isActive } = await helpersContract.getReserveConfigurationData(weth.address); + expect(isActive).to.be.equal(true); + }); + + it('Check the onlyAaveAdmin on deactivateReserve ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).deactivateReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Check the onlyAaveAdmin on activateReserve ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).activateReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Freezes the ETH reserve', async () => { + const { configurator, weth, helpersContract } = testEnv; + + await configurator.freezeReserve(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(true); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Unfreezes the ETH reserve', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.unfreezeReserve(weth.address); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Check the onlyAaveAdmin on freezeReserve ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).freezeReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Check the onlyAaveAdmin on unfreezeReserve ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).unfreezeReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Deactivates the ETH reserve for borrowing', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.disableBorrowingOnReserve(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(false); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Activates the ETH reserve for borrowing', async () => { + const { configurator, weth, helpersContract } = testEnv; + await configurator.enableBorrowingOnReserve(weth.address, true); + const { variableBorrowIndex } = await helpersContract.getReserveData(weth.address); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + + expect(variableBorrowIndex.toString()).to.be.equal(RAY); + }); + + it('Check the onlyAaveAdmin on disableBorrowingOnReserve ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).disableBorrowingOnReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, true), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Deactivates the ETH reserve as collateral', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.configureReserveAsCollateral(weth.address, 0, 0, 0); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(18); + expect(ltv).to.be.equal(0); + expect(liquidationThreshold).to.be.equal(0); + expect(liquidationBonus).to.be.equal(0); + expect(stableBorrowRateEnabled).to.be.equal(true); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Activates the ETH reserve as collateral', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.configureReserveAsCollateral(weth.address, '8000', '8250', '10500'); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Check the onlyAaveAdmin on configureReserveAsCollateral ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator + .connect(users[2].signer) + .configureReserveAsCollateral(weth.address, '7500', '8000', '10500'), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Disable stable borrow rate on the ETH reserve', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.disableReserveStableRate(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(false); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Enables stable borrow rate on the ETH reserve', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.enableReserveStableRate(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(true); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Check the onlyAaveAdmin on disableReserveStableRate', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).disableReserveStableRate(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Check the onlyAaveAdmin on enableReserveStableRate', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).enableReserveStableRate(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Changes the reserve factor of WETH', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.setReserveFactor(weth.address, '1000'); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(1000); + }); + + it('Check the onlyLendingPoolManager on setReserveFactor', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).setReserveFactor(weth.address, '2000'), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Reverts when trying to disable the DAI reserve with liquidity on it', async () => { + const { dai, pool, configurator } = testEnv; + const userAddress = await pool.signer.getAddress(); + await dai.mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access depositor wallet + await dai.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + //user 1 deposits 1000 DAI + await pool.deposit(dai.address, amountDAItoDeposit, userAddress, '0'); + + await expect( + configurator.deactivateReserve(dai.address), + LPC_RESERVE_LIQUIDITY_NOT_0 + ).to.be.revertedWith(LPC_RESERVE_LIQUIDITY_NOT_0); + }); +}); diff --git a/test-suites/test-aave/delegation-aware-atoken.spec.ts b/test-suites/test-aave/delegation-aware-atoken.spec.ts new file mode 100644 index 00000000..656f7422 --- /dev/null +++ b/test-suites/test-aave/delegation-aware-atoken.spec.ts @@ -0,0 +1,64 @@ +import { MAX_UINT_AMOUNT, ZERO_ADDRESS } from '../../helpers/constants'; +import { BUIDLEREVM_CHAINID } from '../../helpers/buidler-constants'; +import { buildPermitParams, getSignatureFromTypedData } from '../../helpers/contracts-helpers'; +import { expect } from 'chai'; +import { ethers } from 'ethers'; +import { eEthereumNetwork, ProtocolErrors } from '../../helpers/types'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { DRE } from '../../helpers/misc-utils'; +import { + ConfigNames, + getATokenDomainSeparatorPerNetwork, + getTreasuryAddress, + loadPoolConfig, +} from '../../helpers/configuration'; +import { waitForTx } from '../../helpers/misc-utils'; +import { + deployDelegationAwareAToken, + deployMintableDelegationERC20, +} from '../../helpers/contracts-deployments'; +import { DelegationAwareATokenFactory } from '../../types'; +import { DelegationAwareAToken } from '../../types/DelegationAwareAToken'; +import { MintableDelegationERC20 } from '../../types/MintableDelegationERC20'; +import AaveConfig from '../../markets/aave'; + +const { parseEther } = ethers.utils; + +makeSuite('AToken: underlying delegation', (testEnv: TestEnv) => { + const poolConfig = loadPoolConfig(ConfigNames.Commons); + let delegationAToken = {}; + let delegationERC20 = {}; + + it('Deploys a new MintableDelegationERC20 and a DelegationAwareAToken', async () => { + const { pool } = testEnv; + + delegationERC20 = await deployMintableDelegationERC20(['DEL', 'DEL', '18']); + + delegationAToken = await deployDelegationAwareAToken( + [pool.address, delegationERC20.address, await getTreasuryAddress(AaveConfig), ZERO_ADDRESS, 'aDEL', 'aDEL'], + false + ); + + //await delegationAToken.initialize(pool.address, ZERO_ADDRESS, delegationERC20.address, ZERO_ADDRESS, '18', 'aDEL', 'aDEL'); + + console.log((await delegationAToken.decimals()).toString()); + }); + + it('Tries to delegate with the caller not being the Aave admin', async () => { + const { users } = testEnv; + + await expect( + delegationAToken.connect(users[1].signer).delegateUnderlyingTo(users[2].address) + ).to.be.revertedWith(ProtocolErrors.CALLER_NOT_POOL_ADMIN); + }); + + it('Tries to delegate to user 2', async () => { + const { users } = testEnv; + + await delegationAToken.delegateUnderlyingTo(users[2].address); + + const delegateeAddress = await delegationERC20.delegatee(); + + expect(delegateeAddress).to.be.equal(users[2].address); + }); +}); diff --git a/test-suites/test-aave/flashloan.spec.ts b/test-suites/test-aave/flashloan.spec.ts new file mode 100644 index 00000000..4a5f5576 --- /dev/null +++ b/test-suites/test-aave/flashloan.spec.ts @@ -0,0 +1,497 @@ +import BigNumber from 'bignumber.js'; + +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { APPROVAL_AMOUNT_LENDING_POOL, oneRay } from '../../helpers/constants'; +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, + getStableDebtToken, + getVariableDebtToken, +} from '../../helpers/contracts-getters'; + +const { expect } = require('chai'); + +makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { + let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver; + const { + VL_COLLATERAL_BALANCE_IS_0, + TRANSFER_AMOUNT_EXCEEDS_BALANCE, + LP_INVALID_FLASHLOAN_MODE, + SAFEERC20_LOWLEVEL_CALL, + LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN, + LP_BORROW_ALLOWANCE_NOT_ENOUGH, + } = ProtocolErrors; + + before(async () => { + _mockFlashLoanReceiver = await getMockFlashLoanReceiver(); + }); + + it('Deposits WETH into the reserve', async () => { + const { pool, weth } = testEnv; + const userAddress = await pool.signer.getAddress(); + const amountToDeposit = ethers.utils.parseEther('1'); + + await weth.mint(amountToDeposit); + + await weth.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool.deposit(weth.address, amountToDeposit, userAddress, '0'); + }); + + it('Takes WETH flashloan with mode = 0, returns the funds correctly', async () => { + const { pool, helpersContract, weth } = testEnv; + + await pool.flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [ethers.utils.parseEther('0.8')], + [0], + _mockFlashLoanReceiver.address, + '0x10', + '0' + ); + + ethers.utils.parseUnits('10000'); + + const reserveData = await helpersContract.getReserveData(weth.address); + + const currentLiquidityRate = reserveData.liquidityRate; + const currentLiquidityIndex = reserveData.liquidityIndex; + + const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) + .plus(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()); + + expect(totalLiquidity.toString()).to.be.equal('1000720000000000000'); + expect(currentLiquidityRate.toString()).to.be.equal('0'); + expect(currentLiquidityIndex.toString()).to.be.equal('1000720000000000000000000000'); + }); + + it('Takes an ETH flashloan with mode = 0 as big as the available liquidity', async () => { + const { pool, helpersContract, weth } = testEnv; + + const reserveDataBefore = await helpersContract.getReserveData(weth.address); + const txResult = await pool.flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + ['1000720000000000000'], + [0], + _mockFlashLoanReceiver.address, + '0x10', + '0' + ); + + const reserveData = await helpersContract.getReserveData(weth.address); + + const currentLiqudityRate = reserveData.liquidityRate; + const currentLiquidityIndex = reserveData.liquidityIndex; + + const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) + .plus(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()); + + expect(totalLiquidity.toString()).to.be.equal('1001620648000000000'); + expect(currentLiqudityRate.toString()).to.be.equal('0'); + expect(currentLiquidityIndex.toString()).to.be.equal('1001620648000000000000000000'); + }); + + it('Takes WETH flashloan, does not return the funds with mode = 0. (revert expected)', async () => { + const { pool, weth, users } = testEnv; + const caller = users[1]; + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [ethers.utils.parseEther('0.8')], + [0], + caller.address, + '0x10', + '0' + ) + ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); + }); + + it('Takes WETH flashloan, simulating a receiver as EOA (revert expected)', async () => { + const { pool, weth, users } = testEnv; + const caller = users[1]; + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + await _mockFlashLoanReceiver.setSimulateEOA(true); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [ethers.utils.parseEther('0.8')], + [0], + caller.address, + '0x10', + '0' + ) + ).to.be.revertedWith(LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN); + }); + + it('Takes a WETH flashloan with an invalid mode. (revert expected)', async () => { + const { pool, weth, users } = testEnv; + const caller = users[1]; + await _mockFlashLoanReceiver.setSimulateEOA(false); + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [ethers.utils.parseEther('0.8')], + [4], + caller.address, + '0x10', + '0' + ) + ).to.be.reverted; + }); + + it('Caller deposits 1000 DAI as collateral, Takes WETH flashloan with mode = 2, does not return the funds. A variable loan for caller is created', async () => { + const { dai, pool, weth, users, helpersContract } = testEnv; + + const caller = users[1]; + + await dai.connect(caller.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + await dai.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const amountToDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool.connect(caller.signer).deposit(dai.address, amountToDeposit, caller.address, '0'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + await pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [ethers.utils.parseEther('0.8')], + [2], + caller.address, + '0x10', + '0' + ); + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const wethDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + const callerDebt = await wethDebtToken.balanceOf(caller.address); + + expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt'); + }); + + it('tries to take a flashloan that is bigger than the available liquidity (revert expected)', async () => { + const { pool, weth, users } = testEnv; + const caller = users[1]; + + await expect( + pool.connect(caller.signer).flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + ['1004415000000000000'], //slightly higher than the available liquidity + [2], + caller.address, + '0x10', + '0' + ), + TRANSFER_AMOUNT_EXCEEDS_BALANCE + ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); + }); + + it('tries to take a flashloan using a non contract address as receiver (revert expected)', async () => { + const { pool, deployer, weth, users } = testEnv; + const caller = users[1]; + + await expect( + pool.flashLoan( + deployer.address, + [weth.address], + ['1000000000000000000'], + [2], + caller.address, + '0x10', + '0' + ) + ).to.be.reverted; + }); + + it('Deposits USDC into the reserve', async () => { + const { usdc, pool } = testEnv; + const userAddress = await pool.signer.getAddress(); + + await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + await usdc.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const amountToDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); + + await pool.deposit(usdc.address, amountToDeposit, userAddress, '0'); + }); + + it('Takes out a 500 USDC flashloan, returns the funds correctly', async () => { + const { usdc, pool, helpersContract, deployer: depositor } = testEnv; + + await _mockFlashLoanReceiver.setFailExecutionTransfer(false); + + const reserveDataBefore = await helpersContract.getReserveData(usdc.address); + + const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); + + await pool.flashLoan( + _mockFlashLoanReceiver.address, + [usdc.address], + [flashloanAmount], + [0], + _mockFlashLoanReceiver.address, + '0x10', + '0' + ); + + const reserveDataAfter = helpersContract.getReserveData(usdc.address); + + const reserveData = await helpersContract.getReserveData(usdc.address); + const userData = await helpersContract.getUserReserveData(usdc.address, depositor.address); + + const totalLiquidity = reserveData.availableLiquidity + .add(reserveData.totalStableDebt) + .add(reserveData.totalVariableDebt) + .toString(); + const currentLiqudityRate = reserveData.liquidityRate.toString(); + const currentLiquidityIndex = reserveData.liquidityIndex.toString(); + const currentUserBalance = userData.currentATokenBalance.toString(); + + const expectedLiquidity = await convertToCurrencyDecimals(usdc.address, '1000.450'); + + expect(totalLiquidity).to.be.equal(expectedLiquidity, 'Invalid total liquidity'); + expect(currentLiqudityRate).to.be.equal('0', 'Invalid liquidity rate'); + expect(currentLiquidityIndex).to.be.equal( + new BigNumber('1.00045').multipliedBy(oneRay).toFixed(), + 'Invalid liquidity index' + ); + expect(currentUserBalance.toString()).to.be.equal(expectedLiquidity, 'Invalid user balance'); + }); + + it('Takes out a 500 USDC flashloan with mode = 0, does not return the funds. (revert expected)', async () => { + const { usdc, pool, users } = testEnv; + const caller = users[2]; + + const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [usdc.address], + [flashloanAmount], + [2], + caller.address, + '0x10', + '0' + ) + ).to.be.revertedWith(VL_COLLATERAL_BALANCE_IS_0); + }); + + it('Caller deposits 5 WETH as collateral, Takes a USDC flashloan with mode = 2, does not return the funds. A loan for caller is created', async () => { + const { usdc, pool, weth, users, helpersContract } = testEnv; + + const caller = users[2]; + + await weth.connect(caller.signer).mint(await convertToCurrencyDecimals(weth.address, '5')); + + await weth.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const amountToDeposit = await convertToCurrencyDecimals(weth.address, '5'); + + await pool.connect(caller.signer).deposit(weth.address, amountToDeposit, caller.address, '0'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); + + await pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [usdc.address], + [flashloanAmount], + [2], + caller.address, + '0x10', + '0' + ); + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + usdc.address + ); + + const usdcDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + const callerDebt = await usdcDebtToken.balanceOf(caller.address); + + expect(callerDebt.toString()).to.be.equal('500000000', 'Invalid user debt'); + }); + + it('Caller deposits 1000 DAI as collateral, Takes a WETH flashloan with mode = 0, does not approve the transfer of the funds', async () => { + const { dai, pool, weth, users } = testEnv; + const caller = users[3]; + + await dai.connect(caller.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + await dai.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const amountToDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool.connect(caller.signer).deposit(dai.address, amountToDeposit, caller.address, '0'); + + const flashAmount = ethers.utils.parseEther('0.8'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(false); + await _mockFlashLoanReceiver.setAmountToApprove(flashAmount.div(2)); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [flashAmount], + [0], + caller.address, + '0x10', + '0' + ) + ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); + }); + + it('Caller takes a WETH flashloan with mode = 1', async () => { + const { dai, pool, weth, users, helpersContract } = testEnv; + + const caller = users[3]; + + const flashAmount = ethers.utils.parseEther('0.8'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + await pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [flashAmount], + [1], + caller.address, + '0x10', + '0' + ); + + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const wethDebtToken = await getStableDebtToken(stableDebtTokenAddress); + + const callerDebt = await wethDebtToken.balanceOf(caller.address); + + 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(LP_BORROW_ALLOWANCE_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'); + + const reserveData = await pool.getReserveData(weth.address); + + const stableDebtToken = await getVariableDebtToken(reserveData.stableDebtTokenAddress); + + // Deposited for onBehalfOf user already, delegate borrow allowance + await stableDebtToken.connect(onBehalfOf.signer).approveDelegation(caller.address, 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 getStableDebtToken(stableDebtTokenAddress); + + const onBehalfOfDebt = await wethDebtToken.balanceOf(onBehalfOf.address); + + expect(onBehalfOfDebt.toString()).to.be.equal( + '800000000000000000', + 'Invalid onBehalfOf user debt' + ); + }); +}); diff --git a/test-suites/test-aave/helpers/actions.ts b/test-suites/test-aave/helpers/actions.ts new file mode 100644 index 00000000..3000576a --- /dev/null +++ b/test-suites/test-aave/helpers/actions.ts @@ -0,0 +1,770 @@ +import BigNumber from 'bignumber.js'; + +import { + calcExpectedReserveDataAfterBorrow, + calcExpectedReserveDataAfterDeposit, + calcExpectedReserveDataAfterRepay, + calcExpectedReserveDataAfterStableRateRebalance, + calcExpectedReserveDataAfterSwapRateMode, + calcExpectedReserveDataAfterWithdraw, + calcExpectedUserDataAfterBorrow, + calcExpectedUserDataAfterDeposit, + calcExpectedUserDataAfterRepay, + calcExpectedUserDataAfterSetUseAsCollateral, + calcExpectedUserDataAfterStableRateRebalance, + calcExpectedUserDataAfterSwapRateMode, + calcExpectedUserDataAfterWithdraw, +} from './utils/calculations'; +import { getReserveAddressFromSymbol, getReserveData, getUserData } from './utils/helpers'; + +import { convertToCurrencyDecimals } from '../../../helpers/contracts-helpers'; +import { + getAToken, + getMintableERC20, + getStableDebtToken, + getVariableDebtToken, +} from '../../../helpers/contracts-getters'; +import { MAX_UINT_AMOUNT, ONE_YEAR } from '../../../helpers/constants'; +import { SignerWithAddress, TestEnv } from './make-suite'; +import { advanceTimeAndBlock, DRE, timeLatest, waitForTx } from '../../../helpers/misc-utils'; + +import chai from 'chai'; +import { ReserveData, UserReserveData } from './utils/interfaces'; +import { ContractReceipt } from 'ethers'; +import { AToken } from '../../../types/AToken'; +import { RateMode, tEthereumAddress } from '../../../helpers/types'; + +const { expect } = chai; + +const almostEqualOrEqual = function ( + this: any, + expected: ReserveData | UserReserveData, + actual: ReserveData | UserReserveData +) { + const keys = Object.keys(actual); + + keys.forEach((key) => { + if ( + key === 'lastUpdateTimestamp' || + key === 'marketStableRate' || + key === 'symbol' || + key === 'aTokenAddress' || + key === 'decimals' || + key === 'totalStableDebtLastUpdated' + ) { + // skipping consistency check on accessory data + return; + } + + this.assert(actual[key] != undefined, `Property ${key} is undefined in the actual data`); + expect(expected[key] != undefined, `Property ${key} is undefined in the expected data`); + + if (expected[key] == null || actual[key] == null) { + console.log('Found a undefined value for Key ', key, ' value ', expected[key], actual[key]); + } + + if (actual[key] instanceof BigNumber) { + const actualValue = (actual[key]).decimalPlaces(0, BigNumber.ROUND_DOWN); + const expectedValue = (expected[key]).decimalPlaces(0, BigNumber.ROUND_DOWN); + + this.assert( + actualValue.eq(expectedValue) || + actualValue.plus(1).eq(expectedValue) || + actualValue.eq(expectedValue.plus(1)) || + actualValue.plus(2).eq(expectedValue) || + actualValue.eq(expectedValue.plus(2)) || + actualValue.plus(3).eq(expectedValue) || + actualValue.eq(expectedValue.plus(3)), + `expected #{act} to be almost equal or equal #{exp} for property ${key}`, + `expected #{act} to be almost equal or equal #{exp} for property ${key}`, + expectedValue.toFixed(0), + actualValue.toFixed(0) + ); + } else { + this.assert( + actual[key] !== null && + expected[key] !== null && + actual[key].toString() === expected[key].toString(), + `expected #{act} to be equal #{exp} for property ${key}`, + `expected #{act} to be equal #{exp} for property ${key}`, + expected[key], + actual[key] + ); + } + }); +}; + +chai.use(function (chai: any, utils: any) { + chai.Assertion.overwriteMethod('almostEqualOrEqual', function (original: any) { + return function (this: any, expected: ReserveData | UserReserveData) { + const actual = (expected as ReserveData) + ? this._obj + : this._obj; + + almostEqualOrEqual.apply(this, [expected, actual]); + }; + }); +}); + +interface ActionsConfig { + skipIntegrityCheck: boolean; +} + +export const configuration: ActionsConfig = {}; + +export const mint = async (reserveSymbol: string, amount: string, user: SignerWithAddress) => { + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const token = await getMintableERC20(reserve); + + await waitForTx( + await token.connect(user.signer).mint(await convertToCurrencyDecimals(reserve, amount)) + ); +}; + +export const approve = async (reserveSymbol: string, user: SignerWithAddress, testEnv: TestEnv) => { + const { pool } = testEnv; + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const token = await getMintableERC20(reserve); + + await waitForTx( + await token.connect(user.signer).approve(pool.address, '100000000000000000000000000000') + ); +}; + +export const deposit = async ( + reserveSymbol: string, + amount: string, + sender: SignerWithAddress, + onBehalfOf: tEthereumAddress, + sendValue: string, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const amountToDeposit = await convertToCurrencyDecimals(reserve, amount); + + const txOptions: any = {}; + + const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( + reserve, + onBehalfOf, + testEnv, + sender.address + ); + + if (sendValue) { + txOptions.value = await convertToCurrencyDecimals(reserve, sendValue); + } + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool + .connect(sender.signer) + .deposit(reserve, amountToDeposit, onBehalfOf, '0', txOptions) + ); + + const { + reserveData: reserveDataAfter, + userData: userDataAfter, + timestamp, + } = await getContractsData(reserve, onBehalfOf, testEnv, sender.address); + + const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); + + const expectedReserveData = calcExpectedReserveDataAfterDeposit( + amountToDeposit.toString(), + reserveDataBefore, + txTimestamp + ); + + const expectedUserReserveData = calcExpectedUserDataAfterDeposit( + amountToDeposit.toString(), + reserveDataBefore, + expectedReserveData, + userDataBefore, + txTimestamp, + timestamp, + txCost + ); + + expectEqual(reserveDataAfter, expectedReserveData); + expectEqual(userDataAfter, expectedUserReserveData); + + // truffleAssert.eventEmitted(txResult, "Deposit", (ev: any) => { + // const {_reserve, _user, _amount} = ev; + // return ( + // _reserve === reserve && + // _user === user && + // new BigNumber(_amount).isEqualTo(new BigNumber(amountToDeposit)) + // ); + // }); + } else if (expectedResult === 'revert') { + await expect( + pool.connect(sender.signer).deposit(reserve, amountToDeposit, onBehalfOf, '0', txOptions), + revertMessage + ).to.be.reverted; + } +}; + +export const withdraw = async ( + reserveSymbol: string, + amount: string, + user: SignerWithAddress, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const { + aTokenInstance, + reserve, + userData: userDataBefore, + reserveData: reserveDataBefore, + } = await getDataBeforeAction(reserveSymbol, user.address, testEnv); + + let amountToWithdraw = '0'; + + if (amount !== '-1') { + amountToWithdraw = (await convertToCurrencyDecimals(reserve, amount)).toString(); + } else { + amountToWithdraw = MAX_UINT_AMOUNT; + } + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool.connect(user.signer).withdraw(reserve, amountToWithdraw, user.address) + ); + + const { + reserveData: reserveDataAfter, + userData: userDataAfter, + timestamp, + } = await getContractsData(reserve, user.address, testEnv); + + const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); + + const expectedReserveData = calcExpectedReserveDataAfterWithdraw( + amountToWithdraw, + reserveDataBefore, + userDataBefore, + txTimestamp + ); + + const expectedUserData = calcExpectedUserDataAfterWithdraw( + amountToWithdraw, + reserveDataBefore, + expectedReserveData, + userDataBefore, + txTimestamp, + timestamp, + txCost + ); + + expectEqual(reserveDataAfter, expectedReserveData); + expectEqual(userDataAfter, expectedUserData); + + // truffleAssert.eventEmitted(txResult, "Redeem", (ev: any) => { + // const {_from, _value} = ev; + // return ( + // _from === user && new BigNumber(_value).isEqualTo(actualAmountRedeemed) + // ); + // }); + } else if (expectedResult === 'revert') { + await expect( + pool.connect(user.signer).withdraw(reserve, amountToWithdraw, user.address), + revertMessage + ).to.be.reverted; + } +}; + +export const delegateBorrowAllowance = async ( + reserve: string, + amount: string, + interestRateMode: string, + user: SignerWithAddress, + receiver: tEthereumAddress, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const reserveAddress: tEthereumAddress = await getReserveAddressFromSymbol(reserve); + + const amountToDelegate: string = await ( + await convertToCurrencyDecimals(reserveAddress, amount) + ).toString(); + + const reserveData = await pool.getReserveData(reserveAddress); + + const debtToken = + interestRateMode === '1' + ? await getStableDebtToken(reserveData.stableDebtTokenAddress) + : await getVariableDebtToken(reserveData.variableDebtTokenAddress); + + const delegateAllowancePromise = debtToken + .connect(user.signer) + .approveDelegation(receiver, amountToDelegate); + + if (expectedResult === 'revert' && revertMessage) { + await expect(delegateAllowancePromise, revertMessage).to.be.revertedWith(revertMessage); + return; + } else { + await waitForTx(await delegateAllowancePromise); + const allowance = await debtToken.borrowAllowance(user.address, receiver); + expect(allowance.toString()).to.be.equal( + amountToDelegate, + 'borrowAllowance is set incorrectly' + ); + } +}; + +export const borrow = async ( + reserveSymbol: string, + amount: string, + interestRateMode: string, + user: SignerWithAddress, + onBehalfOf: tEthereumAddress, + timeTravel: string, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( + reserve, + onBehalfOf, + testEnv, + user.address + ); + + const amountToBorrow = await convertToCurrencyDecimals(reserve, amount); + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool + .connect(user.signer) + .borrow(reserve, amountToBorrow, interestRateMode, '0', onBehalfOf) + ); + + const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); + + if (timeTravel) { + const secondsToTravel = new BigNumber(timeTravel).multipliedBy(ONE_YEAR).div(365).toNumber(); + + await advanceTimeAndBlock(secondsToTravel); + } + + const { + reserveData: reserveDataAfter, + userData: userDataAfter, + timestamp, + } = await getContractsData(reserve, onBehalfOf, testEnv, user.address); + + const expectedReserveData = calcExpectedReserveDataAfterBorrow( + amountToBorrow.toString(), + interestRateMode, + reserveDataBefore, + userDataBefore, + txTimestamp, + timestamp + ); + + const expectedUserData = calcExpectedUserDataAfterBorrow( + amountToBorrow.toString(), + interestRateMode, + reserveDataBefore, + expectedReserveData, + userDataBefore, + txTimestamp, + timestamp + ); + + expectEqual(reserveDataAfter, expectedReserveData); + expectEqual(userDataAfter, expectedUserData); + + // truffleAssert.eventEmitted(txResult, "Borrow", (ev: any) => { + // const { + // _reserve, + // _user, + // _amount, + // _borrowRateMode, + // _borrowRate, + // _originationFee, + // } = ev; + // return ( + // _reserve.toLowerCase() === reserve.toLowerCase() && + // _user.toLowerCase() === user.toLowerCase() && + // new BigNumber(_amount).eq(amountToBorrow) && + // new BigNumber(_borrowRateMode).eq(expectedUserData.borrowRateMode) && + // new BigNumber(_borrowRate).eq(expectedUserData.borrowRate) && + // new BigNumber(_originationFee).eq( + // expectedUserData.originationFee.minus(userDataBefore.originationFee) + // ) + // ); + // }); + } else if (expectedResult === 'revert') { + await expect( + pool.connect(user.signer).borrow(reserve, amountToBorrow, interestRateMode, '0', onBehalfOf), + revertMessage + ).to.be.reverted; + } +}; + +export const repay = async ( + reserveSymbol: string, + amount: string, + rateMode: string, + user: SignerWithAddress, + onBehalfOf: SignerWithAddress, + sendValue: string, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( + reserve, + onBehalfOf.address, + testEnv + ); + + let amountToRepay = '0'; + + if (amount !== '-1') { + amountToRepay = (await convertToCurrencyDecimals(reserve, amount)).toString(); + } else { + amountToRepay = MAX_UINT_AMOUNT; + } + amountToRepay = '0x' + new BigNumber(amountToRepay).toString(16); + + const txOptions: any = {}; + + if (sendValue) { + const valueToSend = await convertToCurrencyDecimals(reserve, sendValue); + txOptions.value = '0x' + new BigNumber(valueToSend.toString()).toString(16); + } + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool + .connect(user.signer) + .repay(reserve, amountToRepay, rateMode, onBehalfOf.address, txOptions) + ); + + const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); + + const { + reserveData: reserveDataAfter, + userData: userDataAfter, + timestamp, + } = await getContractsData(reserve, onBehalfOf.address, testEnv); + + const expectedReserveData = calcExpectedReserveDataAfterRepay( + amountToRepay, + rateMode, + reserveDataBefore, + userDataBefore, + txTimestamp, + timestamp + ); + + const expectedUserData = calcExpectedUserDataAfterRepay( + amountToRepay, + rateMode, + reserveDataBefore, + expectedReserveData, + userDataBefore, + user.address, + onBehalfOf.address, + txTimestamp, + timestamp + ); + + expectEqual(reserveDataAfter, expectedReserveData); + expectEqual(userDataAfter, expectedUserData); + + // truffleAssert.eventEmitted(txResult, "Repay", (ev: any) => { + // const {_reserve, _user, _repayer} = ev; + + // return ( + // _reserve.toLowerCase() === reserve.toLowerCase() && + // _user.toLowerCase() === onBehalfOf.toLowerCase() && + // _repayer.toLowerCase() === user.toLowerCase() + // ); + // }); + } else if (expectedResult === 'revert') { + await expect( + pool + .connect(user.signer) + .repay(reserve, amountToRepay, rateMode, onBehalfOf.address, txOptions), + revertMessage + ).to.be.reverted; + } +}; + +export const setUseAsCollateral = async ( + reserveSymbol: string, + user: SignerWithAddress, + useAsCollateral: string, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( + reserve, + user.address, + testEnv + ); + + const useAsCollateralBool = useAsCollateral.toLowerCase() === 'true'; + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool.connect(user.signer).setUserUseReserveAsCollateral(reserve, useAsCollateralBool) + ); + + const { txCost } = await getTxCostAndTimestamp(txResult); + + const { userData: userDataAfter } = await getContractsData(reserve, user.address, testEnv); + + const expectedUserData = calcExpectedUserDataAfterSetUseAsCollateral( + useAsCollateral.toLocaleLowerCase() === 'true', + reserveDataBefore, + userDataBefore, + txCost + ); + + expectEqual(userDataAfter, expectedUserData); + // if (useAsCollateralBool) { + // truffleAssert.eventEmitted(txResult, 'ReserveUsedAsCollateralEnabled', (ev: any) => { + // const {_reserve, _user} = ev; + // return _reserve === reserve && _user === user; + // }); + // } else { + // truffleAssert.eventEmitted(txResult, 'ReserveUsedAsCollateralDisabled', (ev: any) => { + // const {_reserve, _user} = ev; + // return _reserve === reserve && _user === user; + // }); + // } + } else if (expectedResult === 'revert') { + await expect( + pool.connect(user.signer).setUserUseReserveAsCollateral(reserve, useAsCollateralBool), + revertMessage + ).to.be.reverted; + } +}; + +export const swapBorrowRateMode = async ( + reserveSymbol: string, + user: SignerWithAddress, + rateMode: string, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( + reserve, + user.address, + testEnv + ); + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool.connect(user.signer).swapBorrowRateMode(reserve, rateMode) + ); + + const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); + + const { reserveData: reserveDataAfter, userData: userDataAfter } = await getContractsData( + reserve, + user.address, + testEnv + ); + + const expectedReserveData = calcExpectedReserveDataAfterSwapRateMode( + reserveDataBefore, + userDataBefore, + rateMode, + txTimestamp + ); + + const expectedUserData = calcExpectedUserDataAfterSwapRateMode( + reserveDataBefore, + expectedReserveData, + userDataBefore, + rateMode, + txCost, + txTimestamp + ); + + expectEqual(reserveDataAfter, expectedReserveData); + expectEqual(userDataAfter, expectedUserData); + + // truffleAssert.eventEmitted(txResult, "Swap", (ev: any) => { + // const {_user, _reserve, _newRateMode, _newRate} = ev; + // return ( + // _user === user && + // _reserve == reserve && + // new BigNumber(_newRateMode).eq(expectedUserData.borrowRateMode) && + // new BigNumber(_newRate).eq(expectedUserData.borrowRate) + // ); + // }); + } else if (expectedResult === 'revert') { + await expect(pool.connect(user.signer).swapBorrowRateMode(reserve, rateMode), revertMessage).to + .be.reverted; + } +}; + +export const rebalanceStableBorrowRate = async ( + reserveSymbol: string, + user: SignerWithAddress, + target: SignerWithAddress, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( + reserve, + target.address, + testEnv + ); + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool.connect(user.signer).rebalanceStableBorrowRate(reserve, target.address) + ); + + const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); + + const { reserveData: reserveDataAfter, userData: userDataAfter } = await getContractsData( + reserve, + target.address, + testEnv + ); + + const expectedReserveData = calcExpectedReserveDataAfterStableRateRebalance( + reserveDataBefore, + userDataBefore, + txTimestamp + ); + + const expectedUserData = calcExpectedUserDataAfterStableRateRebalance( + reserveDataBefore, + expectedReserveData, + userDataBefore, + txCost, + txTimestamp + ); + + expectEqual(reserveDataAfter, expectedReserveData); + expectEqual(userDataAfter, expectedUserData); + + // truffleAssert.eventEmitted(txResult, 'RebalanceStableBorrowRate', (ev: any) => { + // const {_user, _reserve, _newStableRate} = ev; + // return ( + // _user.toLowerCase() === target.toLowerCase() && + // _reserve.toLowerCase() === reserve.toLowerCase() && + // new BigNumber(_newStableRate).eq(expectedUserData.borrowRate) + // ); + // }); + } else if (expectedResult === 'revert') { + await expect( + pool.connect(user.signer).rebalanceStableBorrowRate(reserve, target.address), + revertMessage + ).to.be.reverted; + } +}; + +const expectEqual = ( + actual: UserReserveData | ReserveData, + expected: UserReserveData | ReserveData +) => { + if (!configuration.skipIntegrityCheck) { + // @ts-ignore + expect(actual).to.be.almostEqualOrEqual(expected); + } +}; + +interface ActionData { + reserve: string; + reserveData: ReserveData; + userData: UserReserveData; + aTokenInstance: AToken; +} + +const getDataBeforeAction = async ( + reserveSymbol: string, + user: tEthereumAddress, + testEnv: TestEnv +): Promise => { + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const { reserveData, userData } = await getContractsData(reserve, user, testEnv); + const aTokenInstance = await getAToken(reserveData.aTokenAddress); + return { + reserve, + reserveData, + userData, + aTokenInstance, + }; +}; + +export const getTxCostAndTimestamp = async (tx: ContractReceipt) => { + if (!tx.blockNumber || !tx.transactionHash || !tx.cumulativeGasUsed) { + throw new Error('No tx blocknumber'); + } + const txTimestamp = new BigNumber((await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp); + + const txInfo = await DRE.ethers.provider.getTransaction(tx.transactionHash); + const txCost = new BigNumber(tx.cumulativeGasUsed.toString()).multipliedBy( + txInfo.gasPrice.toString() + ); + + return { txCost, txTimestamp }; +}; + +export const getContractsData = async ( + reserve: string, + user: string, + testEnv: TestEnv, + sender?: string +) => { + const { pool, helpersContract } = testEnv; + + const [userData, reserveData, timestamp] = await Promise.all([ + getUserData(pool, helpersContract, reserve, user, sender || user), + getReserveData(helpersContract, reserve), + timeLatest(), + ]); + + return { + reserveData, + userData, + timestamp: new BigNumber(timestamp), + }; +}; diff --git a/test-suites/test-aave/helpers/almost-equal.ts b/test-suites/test-aave/helpers/almost-equal.ts new file mode 100644 index 00000000..e0017056 --- /dev/null +++ b/test-suites/test-aave/helpers/almost-equal.ts @@ -0,0 +1,31 @@ +import BigNumber from 'bignumber.js'; + +function almostEqualAssertion(this: any, expected: any, actual: any, message: string): any { + this.assert( + expected.plus(new BigNumber(1)).eq(actual) || + expected.plus(new BigNumber(2)).eq(actual) || + actual.plus(new BigNumber(1)).eq(expected) || + actual.plus(new BigNumber(2)).eq(expected) || + expected.eq(actual), + `${message} expected #{act} to be almost equal #{exp}`, + `${message} expected #{act} to be different from #{exp}`, + expected.toString(), + actual.toString() + ); +} + +export function almostEqual() { + return function (chai: any, utils: any) { + chai.Assertion.overwriteMethod('almostEqual', function (original: any) { + return function (this: any, value: any, message: string) { + if (utils.flag(this, 'bignumber')) { + var expected = new BigNumber(value); + var actual = new BigNumber(this._obj); + almostEqualAssertion.apply(this, [expected, actual, message]); + } else { + original.apply(this, arguments); + } + }; + }); + }; +} diff --git a/test-suites/test-aave/helpers/make-suite.ts b/test-suites/test-aave/helpers/make-suite.ts new file mode 100644 index 00000000..e56358be --- /dev/null +++ b/test-suites/test-aave/helpers/make-suite.ts @@ -0,0 +1,191 @@ +import { evmRevert, evmSnapshot, DRE } from '../../../helpers/misc-utils'; +import { Signer } from 'ethers'; +import { + getLendingPool, + getLendingPoolAddressesProvider, + getAaveProtocolDataProvider, + getAToken, + getMintableERC20, + getLendingPoolConfiguratorProxy, + getPriceOracle, + getLendingPoolAddressesProviderRegistry, + getWETHMocked, + getWETHGateway, + getUniswapLiquiditySwapAdapter, + getUniswapRepayAdapter, + getFlashLiquidationAdapter, +} from '../../../helpers/contracts-getters'; +import { eEthereumNetwork, tEthereumAddress } from '../../../helpers/types'; +import { LendingPool } from '../../../types/LendingPool'; +import { AaveProtocolDataProvider } from '../../../types/AaveProtocolDataProvider'; +import { MintableERC20 } from '../../../types/MintableERC20'; +import { AToken } from '../../../types/AToken'; +import { LendingPoolConfigurator } from '../../../types/LendingPoolConfigurator'; + +import chai from 'chai'; +// @ts-ignore +import bignumberChai from 'chai-bignumber'; +import { almostEqual } from './almost-equal'; +import { PriceOracle } from '../../../types/PriceOracle'; +import { LendingPoolAddressesProvider } from '../../../types/LendingPoolAddressesProvider'; +import { LendingPoolAddressesProviderRegistry } from '../../../types/LendingPoolAddressesProviderRegistry'; +import { getEthersSigners } from '../../../helpers/contracts-helpers'; +import { UniswapLiquiditySwapAdapter } from '../../../types/UniswapLiquiditySwapAdapter'; +import { UniswapRepayAdapter } from '../../../types/UniswapRepayAdapter'; +import { getParamPerNetwork } from '../../../helpers/contracts-helpers'; +import { WETH9Mocked } from '../../../types/WETH9Mocked'; +import { WETHGateway } from '../../../types/WETHGateway'; +import { solidity } from 'ethereum-waffle'; +import { AaveConfig } from '../../../markets/aave'; +import { FlashLiquidationAdapter } from '../../../types'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { usingTenderly } from '../../../helpers/tenderly-utils'; + +chai.use(bignumberChai()); +chai.use(almostEqual()); +chai.use(solidity); + +export interface SignerWithAddress { + signer: Signer; + address: tEthereumAddress; +} +export interface TestEnv { + deployer: SignerWithAddress; + users: SignerWithAddress[]; + pool: LendingPool; + configurator: LendingPoolConfigurator; + oracle: PriceOracle; + helpersContract: AaveProtocolDataProvider; + weth: WETH9Mocked; + aWETH: AToken; + dai: MintableERC20; + aDai: AToken; + usdc: MintableERC20; + aave: MintableERC20; + addressesProvider: LendingPoolAddressesProvider; + uniswapLiquiditySwapAdapter: UniswapLiquiditySwapAdapter; + uniswapRepayAdapter: UniswapRepayAdapter; + registry: LendingPoolAddressesProviderRegistry; + wethGateway: WETHGateway; + flashLiquidationAdapter: FlashLiquidationAdapter; +} + +let buidlerevmSnapshotId: string = '0x1'; +const setBuidlerevmSnapshotId = (id: string) => { + buidlerevmSnapshotId = id; +}; + +const testEnv: TestEnv = { + deployer: {} as SignerWithAddress, + users: [] as SignerWithAddress[], + pool: {} as LendingPool, + configurator: {} as LendingPoolConfigurator, + helpersContract: {} as AaveProtocolDataProvider, + oracle: {} as PriceOracle, + weth: {} as WETH9Mocked, + aWETH: {} as AToken, + dai: {} as MintableERC20, + aDai: {} as AToken, + usdc: {} as MintableERC20, + aave: {} as MintableERC20, + addressesProvider: {} as LendingPoolAddressesProvider, + uniswapLiquiditySwapAdapter: {} as UniswapLiquiditySwapAdapter, + uniswapRepayAdapter: {} as UniswapRepayAdapter, + flashLiquidationAdapter: {} as FlashLiquidationAdapter, + registry: {} as LendingPoolAddressesProviderRegistry, + wethGateway: {} as WETHGateway, +} as TestEnv; + +export async function initializeMakeSuite() { + const [_deployer, ...restSigners] = await getEthersSigners(); + const deployer: SignerWithAddress = { + address: await _deployer.getAddress(), + signer: _deployer, + }; + + for (const signer of restSigners) { + testEnv.users.push({ + signer, + address: await signer.getAddress(), + }); + } + testEnv.deployer = deployer; + testEnv.pool = await getLendingPool(); + + testEnv.configurator = await getLendingPoolConfiguratorProxy(); + + testEnv.addressesProvider = await getLendingPoolAddressesProvider(); + + if (process.env.MAINNET_FORK === 'true') { + testEnv.registry = await getLendingPoolAddressesProviderRegistry( + getParamPerNetwork(AaveConfig.ProviderRegistry, eEthereumNetwork.main) + ); + } else { + testEnv.registry = await getLendingPoolAddressesProviderRegistry(); + testEnv.oracle = await getPriceOracle(); + } + + testEnv.helpersContract = await getAaveProtocolDataProvider(); + + const allTokens = await testEnv.helpersContract.getAllATokens(); + const aDaiAddress = allTokens.find((aToken) => aToken.symbol === 'aDAI')?.tokenAddress; + + const aWEthAddress = allTokens.find((aToken) => aToken.symbol === 'aWETH')?.tokenAddress; + + const reservesTokens = await testEnv.helpersContract.getAllReservesTokens(); + + const daiAddress = reservesTokens.find((token) => token.symbol === 'DAI')?.tokenAddress; + const usdcAddress = reservesTokens.find((token) => token.symbol === 'USDC')?.tokenAddress; + const aaveAddress = reservesTokens.find((token) => token.symbol === 'AAVE')?.tokenAddress; + const wethAddress = reservesTokens.find((token) => token.symbol === 'WETH')?.tokenAddress; + + if (!aDaiAddress || !aWEthAddress) { + process.exit(1); + } + if (!daiAddress || !usdcAddress || !aaveAddress || !wethAddress) { + process.exit(1); + } + + testEnv.aDai = await getAToken(aDaiAddress); + testEnv.aWETH = await getAToken(aWEthAddress); + + testEnv.dai = await getMintableERC20(daiAddress); + testEnv.usdc = await getMintableERC20(usdcAddress); + testEnv.aave = await getMintableERC20(aaveAddress); + testEnv.weth = await getWETHMocked(wethAddress); + testEnv.wethGateway = await getWETHGateway(); + + testEnv.uniswapLiquiditySwapAdapter = await getUniswapLiquiditySwapAdapter(); + testEnv.uniswapRepayAdapter = await getUniswapRepayAdapter(); + testEnv.flashLiquidationAdapter = await getFlashLiquidationAdapter(); +} + +const setSnapshot = async () => { + const hre = DRE as HardhatRuntimeEnvironment; + if (usingTenderly()) { + setBuidlerevmSnapshotId((await hre.tenderlyRPC.getHead()) || '0x1'); + return; + } + setBuidlerevmSnapshotId(await evmSnapshot()); +}; + +const revertHead = async () => { + const hre = DRE as HardhatRuntimeEnvironment; + if (usingTenderly()) { + await hre.tenderlyRPC.setHead(buidlerevmSnapshotId); + return; + } + await evmRevert(buidlerevmSnapshotId); +}; + +export function makeSuite(name: string, tests: (testEnv: TestEnv) => void) { + describe(name, () => { + before(async () => { + await setSnapshot(); + }); + tests(testEnv); + after(async () => { + await revertHead(); + }); + }); +} diff --git a/test-suites/test-aave/helpers/scenario-engine.ts b/test-suites/test-aave/helpers/scenario-engine.ts new file mode 100644 index 00000000..492fa8b2 --- /dev/null +++ b/test-suites/test-aave/helpers/scenario-engine.ts @@ -0,0 +1,237 @@ +import { TestEnv, SignerWithAddress } from './make-suite'; +import { + mint, + approve, + deposit, + borrow, + withdraw, + repay, + setUseAsCollateral, + swapBorrowRateMode, + rebalanceStableBorrowRate, + delegateBorrowAllowance, +} from './actions'; +import { RateMode } from '../../../helpers/types'; + +export interface Action { + name: string; + args?: any; + expected: string; + revertMessage?: string; +} + +export interface Story { + description: string; + actions: Action[]; +} + +export interface Scenario { + title: string; + description: string; + stories: Story[]; +} + +export const executeStory = async (story: Story, testEnv: TestEnv) => { + for (const action of story.actions) { + const { users } = testEnv; + await executeAction(action, users, testEnv); + } +}; + +const executeAction = async (action: Action, users: SignerWithAddress[], testEnv: TestEnv) => { + const { reserve, user: userIndex, borrowRateMode } = action.args; + const { name, expected, revertMessage } = action; + + if (!name || name === '') { + throw 'Action name is missing'; + } + if (!reserve || reserve === '') { + throw 'Invalid reserve selected for deposit'; + } + if (!userIndex || userIndex === '') { + throw `Invalid user selected to deposit into the ${reserve} reserve`; + } + + if (!expected || expected === '') { + throw `An expected resut for action ${name} is required`; + } + + let rateMode: string = RateMode.None; + + if (borrowRateMode) { + if (borrowRateMode === 'none') { + rateMode = RateMode.None; + } else if (borrowRateMode === 'stable') { + rateMode = RateMode.Stable; + } else if (borrowRateMode === 'variable') { + rateMode = RateMode.Variable; + } else { + //random value, to test improper selection of the parameter + rateMode = '4'; + } + } + + const user = users[parseInt(userIndex)]; + + switch (name) { + case 'mint': + const { amount } = action.args; + + if (!amount || amount === '') { + throw `Invalid amount of ${reserve} to mint`; + } + + await mint(reserve, amount, user); + break; + + case 'approve': + await approve(reserve, user, testEnv); + break; + + case 'deposit': + { + const { amount, sendValue, onBehalfOf: onBehalfOfIndex } = action.args; + const onBehalfOf = onBehalfOfIndex + ? users[parseInt(onBehalfOfIndex)].address + : user.address; + + if (!amount || amount === '') { + throw `Invalid amount to deposit into the ${reserve} reserve`; + } + + await deposit( + reserve, + amount, + user, + onBehalfOf, + sendValue, + expected, + testEnv, + revertMessage + ); + } + break; + + case 'delegateBorrowAllowance': + { + const { amount, toUser: toUserIndex } = action.args; + const toUser = users[parseInt(toUserIndex, 10)].address; + if (!amount || amount === '') { + throw `Invalid amount to deposit into the ${reserve} reserve`; + } + + await delegateBorrowAllowance( + reserve, + amount, + rateMode, + user, + toUser, + expected, + testEnv, + revertMessage + ); + } + break; + + case 'withdraw': + { + const { amount } = action.args; + + if (!amount || amount === '') { + throw `Invalid amount to withdraw from the ${reserve} reserve`; + } + + await withdraw(reserve, amount, user, expected, testEnv, revertMessage); + } + break; + case 'borrow': + { + const { amount, timeTravel, onBehalfOf: onBehalfOfIndex } = action.args; + + const onBehalfOf = onBehalfOfIndex + ? users[parseInt(onBehalfOfIndex)].address + : user.address; + + if (!amount || amount === '') { + throw `Invalid amount to borrow from the ${reserve} reserve`; + } + + await borrow( + reserve, + amount, + rateMode, + user, + onBehalfOf, + timeTravel, + expected, + testEnv, + revertMessage + ); + } + break; + + case 'repay': + { + const { amount, borrowRateMode, sendValue } = action.args; + let { onBehalfOf: onBehalfOfIndex } = action.args; + + if (!amount || amount === '') { + throw `Invalid amount to repay into the ${reserve} reserve`; + } + + let userToRepayOnBehalf: SignerWithAddress; + if (!onBehalfOfIndex || onBehalfOfIndex === '') { + console.log( + 'WARNING: No onBehalfOf specified for a repay action. Defaulting to the repayer address' + ); + userToRepayOnBehalf = user; + } else { + userToRepayOnBehalf = users[parseInt(onBehalfOfIndex)]; + } + + await repay( + reserve, + amount, + rateMode, + user, + userToRepayOnBehalf, + sendValue, + expected, + testEnv, + revertMessage + ); + } + break; + + case 'setUseAsCollateral': + { + const { useAsCollateral } = action.args; + + if (!useAsCollateral || useAsCollateral === '') { + throw `A valid value for useAsCollateral needs to be set when calling setUseReserveAsCollateral on reserve ${reserve}`; + } + await setUseAsCollateral(reserve, user, useAsCollateral, expected, testEnv, revertMessage); + } + break; + + case 'swapBorrowRateMode': + await swapBorrowRateMode(reserve, user, rateMode, expected, testEnv, revertMessage); + break; + + case 'rebalanceStableBorrowRate': + { + const { target: targetIndex } = action.args; + + if (!targetIndex || targetIndex === '') { + throw `A target must be selected when trying to rebalance a stable rate`; + } + const target = users[parseInt(targetIndex)]; + + await rebalanceStableBorrowRate(reserve, user, target, expected, testEnv, revertMessage); + } + break; + + default: + throw `Invalid action requested: ${name}`; + } +}; diff --git a/test-suites/test-aave/helpers/scenarios/borrow-negatives.json b/test-suites/test-aave/helpers/scenarios/borrow-negatives.json new file mode 100644 index 00000000..03f4d005 --- /dev/null +++ b/test-suites/test-aave/helpers/scenarios/borrow-negatives.json @@ -0,0 +1,142 @@ +{ + "title": "LendingPool: Borrow negatives (reverts)", + "description": "Test cases for the deposit function.", + "stories": [ + { + "description": "User 0 deposits 1000 DAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 DAI with rate mode NONE (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "none", + "user": "1" + }, + "expected": "revert", + "revertMessage": "Invalid interest rate mode selected" + } + ] + }, + { + "description": "User 0 deposits 1000 DAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 DAI with an invalid rate mode (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "invalid", + "user": "1" + }, + "expected": "revert", + "revertMessage": "Invalid interest rate mode selected" + } + ] + } + ] +} diff --git a/test-suites/test-aave/helpers/scenarios/borrow-repay-stable.json b/test-suites/test-aave/helpers/scenarios/borrow-repay-stable.json new file mode 100644 index 00000000..bdbf1aff --- /dev/null +++ b/test-suites/test-aave/helpers/scenarios/borrow-repay-stable.json @@ -0,0 +1,656 @@ +{ + "title": "LendingPool: Borrow/repay (stable rate)", + "description": "Test cases for the borrow function, stable mode.", + "stories": [ + { + "description": "User 0 deposits 1000 DAI, user 1 deposits 1 WETH as collateral and borrows 100 DAI at stable rate", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 tries to borrow the rest of the DAI liquidity (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "900", + "borrowRateMode": "stable", + "user": "1" + }, + "expected": "revert", + "revertMessage": "There is not enough collateral to cover a new borrow" + } + ] + }, + { + "description": "User 1 repays half of the DAI borrow after one year", + "actions": [ + { + "name": "mint", + "description": "Mint 10 DAI to cover the interest", + "args": { + "reserve": "DAI", + "amount": "10", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "50", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 repays the rest of the DAI borrow after one year", + "actions": [ + { + "name": "mint", + "description": "Mint 15 DAI to cover the interest", + "args": { + "reserve": "DAI", + "amount": "15", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws the deposited DAI plus interest", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 1000 DAI, user 2 tries to borrow 1000 DAI at a stable rate without any collateral (revert expected) User 1 withdrawws", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "1000", + "borrowRateMode": "stable", + "user": "2" + }, + "expected": "revert", + "revertMessage": "The collateral balance is 0" + }, + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1000 DAI, user 1,2,3,4 deposit 1 WETH each and borrow 100 DAI at stable rate. Everything is repaid, user 0 withdraws", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "2" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "2" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "2" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "2", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "3" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "3" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "3" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "3", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "4" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "4" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "4" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "4", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 15 DAI to cover the interest", + "args": { + "reserve": "DAI", + "amount": "15", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 20 DAI to cover the interest", + "args": { + "reserve": "DAI", + "amount": "20", + "user": "2" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "2" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "2", + "onBehalfOf": "2", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 30 DAI to cover the interest", + "args": { + "reserve": "DAI", + "amount": "30", + "user": "3" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "3" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "3", + "onBehalfOf": "3", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 30 DAI to cover the interest", + "args": { + "reserve": "DAI", + "amount": "30", + "user": "4" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "4" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "4", + "onBehalfOf": "4", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1000 DAI, user 1 deposits 2 WETH and borrow 100 DAI at stable rate first, then 100 DAI at variable rate, repays everything. User 0 withdraws", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "2", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "2", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 50 DAI to cover the interest", + "args": { + "reserve": "DAI", + "amount": "50", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-aave/helpers/scenarios/borrow-repay-variable.json b/test-suites/test-aave/helpers/scenarios/borrow-repay-variable.json new file mode 100644 index 00000000..aa269fd7 --- /dev/null +++ b/test-suites/test-aave/helpers/scenarios/borrow-repay-variable.json @@ -0,0 +1,945 @@ +{ + "title": "LendingPool: Borrow/repay (variable rate)", + "description": "Test cases for the borrow function, variable mode.", + "stories": [ + { + "description": "User 2 deposits 1 DAI to account for rounding errors", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1", + "user": "2" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "2" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1", + "user": "2" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1000 DAI, user 1 deposits 1 WETH as collateral and borrows 100 DAI at variable rate", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 tries to borrow the rest of the DAI liquidity (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "900", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "revert", + "revertMessage": "There is not enough collateral to cover a new borrow" + } + ] + }, + { + "description": "User 1 tries to repay 0 DAI (revert expected)", + "actions": [ + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "0", + "user": "1", + "onBehalfOf": "1" + }, + "expected": "revert", + "revertMessage": "Amount must be greater than 0" + } + ] + }, + { + "description": "User 1 repays a small amount of DAI, enough to cover a small part of the interest", + "actions": [ + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "1.25", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 repays the DAI borrow after one year", + "actions": [ + { + "name": "mint", + "description": "Mint 10 DAI to cover the interest", + "args": { + "reserve": "DAI", + "amount": "10", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws the deposited DAI plus interest", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 withdraws the collateral", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "WETH", + "amount": "-1", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 2 deposits a small amount of WETH to account for rounding errors", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "0.001", + "user": "2" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "2" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "0.001", + "user": "2" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1 WETH, user 1 deposits 100 LINK as collateral and borrows 0.5 WETH at variable rate", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "LINK", + "amount": "100", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "LINK", + "user": "1" + }, + "expected": "success" + }, + + { + "name": "deposit", + "args": { + "reserve": "LINK", + "amount": "100", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "WETH", + "amount": "0.5", + "borrowRateMode": "variable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 tries to repay 0 WETH", + "actions": [ + { + "name": "repay", + "args": { + "reserve": "WETH", + "amount": "0", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "revert", + "revertMessage": "Amount must be greater than 0" + } + ] + }, + { + "description": "User 2 tries to repay everything on behalf of user 1 using uint(-1) (revert expected)", + "actions": [ + { + "name": "repay", + "args": { + "reserve": "WETH", + "amount": "-1", + "user": "2", + "borrowRateMode": "variable", + "onBehalfOf": "1" + }, + "expected": "revert", + "revertMessage": "To repay on behalf of an user an explicit amount to repay is needed" + } + ] + }, + { + "description": "User 3 repays a small amount of WETH on behalf of user 1", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "3" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "3" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "WETH", + "amount": "0.2", + "user": "3", + "borrowRateMode": "variable", + "onBehalfOf": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 repays the WETH borrow after one year", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "2" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "2" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "WETH", + "amount": "-1", + "borrowRateMode": "variable", + "user": "1", + "onBehalfOf": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws the deposited WETH plus interest", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "WETH", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 withdraws the collateral", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "LINK", + "amount": "-1", + "user": "1" + }, + "expected": "success" + } + ] + }, + + { + "description": "User 2 deposits 1 USDC to account for rounding errors", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "USDC", + "amount": "1", + "user": "2" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "USDC", + "user": "2" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "USDC", + "amount": "1", + "user": "2" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1000 USDC, user 1 deposits 1 WETH as collateral and borrows 100 USDC at variable rate", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "USDC", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "USDC", + "amount": "100", + "borrowRateMode": "variable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 tries to borrow the rest of the USDC liquidity (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "USDC", + "amount": "900", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "revert", + "revertMessage": "There is not enough collateral to cover a new borrow" + } + ] + }, + { + "description": "User 1 repays the USDC borrow after one year", + "actions": [ + { + "name": "mint", + "description": "Mint 10 USDC to cover the interest", + "args": { + "reserve": "USDC", + "amount": "10", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "USDC", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "USDC", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws the deposited USDC plus interest", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "USDC", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 withdraws the collateral", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "WETH", + "amount": "-1", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 1000 DAI, user 3 tries to borrow 1000 DAI without any collateral (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "1000", + "borrowRateMode": "variable", + "user": "3" + }, + "expected": "revert", + "revertMessage": "The collateral balance is 0" + } + ] + }, + { + "description": "user 3 deposits 0.1 WETH collateral to borrow 100 DAI; 0.1 WETH is not enough to borrow 100 DAI (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "0.1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "0.1", + "user": "3" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "3" + }, + "expected": "revert", + "revertMessage": "There is not enough collateral to cover a new borrow" + } + ] + }, + { + "description": "user 3 withdraws the 0.1 WETH", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "WETH", + "amount": "-1", + "user": "3" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 1000 USDC, user 3 tries to borrow 1000 USDC without any collateral (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "USDC", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "USDC", + "amount": "1000", + "borrowRateMode": "variable", + "user": "3" + }, + "expected": "revert", + "revertMessage": "The collateral balance is 0" + } + ] + }, + { + "description": "user 3 deposits 0.1 WETH collateral to borrow 100 USDC; 0.1 WETH is not enough to borrow 100 USDC (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "3" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "0.1", + "user": "3" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "USDC", + "amount": "100", + "borrowRateMode": "variable", + "user": "3" + }, + "expected": "revert", + "revertMessage": "There is not enough collateral to cover a new borrow" + } + ] + }, + { + "description": "user 3 withdraws the 0.1 WETH", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "WETH", + "amount": "-1", + "user": "3" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1000 DAI, user 6 deposits 2 WETH and borrow 100 DAI at variable rate first, then 100 DAI at stable rate, repays everything. User 0 withdraws", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "2", + "user": "6" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "6" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "2", + "user": "6" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "6", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "6", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 50 DAI to cover the interest", + "args": { + "reserve": "DAI", + "amount": "50", + "user": "6" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "6" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "6", + "onBehalfOf": "6", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "6", + "onBehalfOf": "6", + "borrowRateMode": "variable" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-aave/helpers/scenarios/credit-delegation.json b/test-suites/test-aave/helpers/scenarios/credit-delegation.json new file mode 100644 index 00000000..2efabeb1 --- /dev/null +++ b/test-suites/test-aave/helpers/scenarios/credit-delegation.json @@ -0,0 +1,157 @@ +{ + "title": "LendingPool: credit delegation", + "description": "Test cases for the credit delegation related functions.", + "stories": [ + { + "description": "User 3 deposits 1000 WETH. User 0 deposits 1000 DAI, user 0 delegates borrowing of 1 WETH on variable to user 4, user 4 borrows 1 WETH variable on behalf of user 0", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1000", + "user": "3" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "3" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1000", + "user": "3" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "delegateBorrowAllowance", + "args": { + "reserve": "WETH", + "amount": "2", + "user": "0", + "borrowRateMode": "variable", + "toUser": "4" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "4", + "onBehalfOf": "0", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 4 trying to borrow 1 WETH stable on behalf of user 0, revert expected", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "4", + "onBehalfOf": "0", + "borrowRateMode": "stable" + }, + "expected": "revert", + "revertMessage": "59" + } + ] + }, + { + "description": "User 0 delegates borrowing of 1 WETH to user 4, user 4 borrows 3 WETH variable on behalf of user 0, revert expected", + "actions": [ + { + "name": "delegateBorrowAllowance", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0", + "borrowRateMode": "variable", + "toUser": "4" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "WETH", + "amount": "3", + "user": "4", + "onBehalfOf": "0", + "borrowRateMode": "variable" + }, + "expected": "revert", + "revertMessage": "59" + } + ] + }, + { + "description": "User 0 delegates borrowing of 1 WETH on stable to user 2, user 2 borrows 1 WETH stable on behalf of user 0", + "actions": [ + { + "name": "delegateBorrowAllowance", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0", + "borrowRateMode": "stable", + "toUser": "2" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "2", + "onBehalfOf": "0", + "borrowRateMode": "stable" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-aave/helpers/scenarios/deposit.json b/test-suites/test-aave/helpers/scenarios/deposit.json new file mode 100644 index 00000000..b4b73879 --- /dev/null +++ b/test-suites/test-aave/helpers/scenarios/deposit.json @@ -0,0 +1,266 @@ +{ + "title": "LendingPool: Deposit", + "description": "Test cases for the deposit function.", + "stories": [ + { + "description": "User 0 Deposits 1000 DAI in an empty reserve", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 1000 DAI after user 0", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1000 USDC in an empty reserve", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "USDC", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 1000 USDC after user 0", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "USDC", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1 WETH in an empty reserve", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 1 WETH after user 0", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 0 WETH (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "0", + "user": "1" + }, + "expected": "revert", + "revertMessage": "Amount must be greater than 0" + } + ] + }, + { + "description": "User 1 deposits 0 DAI", + "actions": [ + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "0", + "user": "1" + }, + "expected": "revert", + "revertMessage": "Amount must be greater than 0" + } + ] + }, + { + "description": "User 1 deposits 100 DAI on behalf of user 2, user 2 tries to borrow 0.1 WETH", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "100", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "100", + "user": "1", + "onBehalfOf": "2" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "WETH", + "amount": "0.1", + "borrowRateMode": "variable", + "user": "2" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-aave/helpers/scenarios/rebalance-stable-rate.json b/test-suites/test-aave/helpers/scenarios/rebalance-stable-rate.json new file mode 100644 index 00000000..79c224f8 --- /dev/null +++ b/test-suites/test-aave/helpers/scenarios/rebalance-stable-rate.json @@ -0,0 +1,198 @@ +{ + "title": "LendingPool: Rebalance stable rate", + "description": "Test cases for the rebalanceStableBorrowRate() function.", + "stories": [ + { + "description": "User 0 tries to rebalance user 1 who has no borrows in progress (revert expected)", + "actions": [ + { + "name": "rebalanceStableBorrowRate", + "args": { + "reserve": "USDC", + "user": "0", + "target": "1" + }, + "expected": "revert", + "revertMessage": "User does not have any stable rate loan for this reserve" + } + ] + }, + { + "description": "User 0 deposits 1000 USDC, user 1 deposits 7 WETH, borrows 250 USDC at a stable rate, user 0 rebalances user 1 (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "USDC", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "7", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "7", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "USDC", + "amount": "250", + "borrowRateMode": "stable", + "user": "1" + }, + "expected": "success" + }, + { + "name": "rebalanceStableBorrowRate", + "args": { + "reserve": "USDC", + "user": "0", + "target": "1" + }, + "expected": "revert", + "revertMessage": "The user borrow is variable and cannot be rebalanced" + } + ] + }, + { + "description": "User 1 borrows another 200 at variable, user 0 tries to rebalance but the conditions are not met (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "USDC", + "amount": "200", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "success" + }, + { + "name": "rebalanceStableBorrowRate", + "args": { + "reserve": "USDC", + "user": "0", + "target": "1" + }, + "expected": "revert", + "revertMessage": "Interest rate rebalance conditions were not met" + } + ] + }, + { + "description": "User 1 borrows another 200 at variable, user 0 tries to rebalance but the conditions are not met (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "USDC", + "amount": "200", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "success" + }, + { + "name": "rebalanceStableBorrowRate", + "args": { + "reserve": "USDC", + "user": "0", + "target": "1" + }, + "expected": "revert", + "revertMessage": "Interest rate rebalance conditions were not met" + } + ] + }, + { + "description": "User 1 borrows another 100 at variable, user 0 tries to rebalance but the conditions are not met (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "USDC", + "amount": "280", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "success" + }, + { + "name": "rebalanceStableBorrowRate", + "args": { + "reserve": "USDC", + "user": "0", + "target": "1" + }, + "expected": "revert", + "revertMessage": "Interest rate rebalance conditions were not met" + } + ] + }, + + { + "description": "User 1 borrows the remaining USDC (usage ratio = 100%) at variable. User 0 rebalances user 1", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "USDC", + "amount": "20", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "success" + }, + { + "name": "rebalanceStableBorrowRate", + "args": { + "reserve": "USDC", + "user": "0", + "target": "1" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-aave/helpers/scenarios/set-use-as-collateral.json b/test-suites/test-aave/helpers/scenarios/set-use-as-collateral.json new file mode 100644 index 00000000..2a206bb9 --- /dev/null +++ b/test-suites/test-aave/helpers/scenarios/set-use-as-collateral.json @@ -0,0 +1,236 @@ +{ + "title": "LendingPool: Usage as collateral", + "description": "Test cases for the setUserUseReserveAsCollateral() function.", + "stories": [ + { + "description": "User 0 Deposits 1000 DAI, disables DAI as collateral", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "setUseAsCollateral", + "args": { + "reserve": "DAI", + "user": "0", + "useAsCollateral": "false" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 Deposits 2 WETH, disables WETH as collateral, borrows 400 DAI (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "2", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "2", + "user": "1" + }, + "expected": "success" + }, + { + "name": "setUseAsCollateral", + "args": { + "reserve": "WETH", + "user": "1", + "useAsCollateral": "false" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "400", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "revert", + "revertMessage": "The collateral balance is 0" + } + ] + }, + { + "description": "User 1 enables WETH as collateral, borrows 400 DAI", + "actions": [ + { + "name": "setUseAsCollateral", + "args": { + "reserve": "WETH", + "user": "1", + "useAsCollateral": "true" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "400", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 disables WETH as collateral (revert expected)", + "actions": [ + { + "name": "setUseAsCollateral", + "args": { + "reserve": "WETH", + "user": "1", + "useAsCollateral": "false" + }, + "expected": "revert", + "revertMessage": "User deposit is already being used as collateral" + } + ] + }, + { + "description": "User 1 Deposits 10 AAVE, disables WETH as collateral. Should revert as 10 AAVE are not enough to cover the debt (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "AAVE", + "amount": "10", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "AAVE", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "AAVE", + "amount": "10", + "user": "1" + }, + "expected": "success" + }, + { + "name": "setUseAsCollateral", + "args": { + "reserve": "WETH", + "user": "1", + "useAsCollateral": "false" + }, + "expected": "revert" + } + ] + }, + { + "description": "User 1 Deposits 640 more AAVE (enough to cover the DAI debt), disables WETH as collateral", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "AAVE", + "amount": "640", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "AAVE", + "amount": "640", + "user": "1" + }, + "expected": "success" + }, + { + "name": "setUseAsCollateral", + "args": { + "reserve": "WETH", + "user": "1", + "useAsCollateral": "false" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 disables AAVE as collateral (revert expected)", + "actions": [ + { + "name": "setUseAsCollateral", + "args": { + "reserve": "AAVE", + "user": "1", + "useAsCollateral": "false" + }, + "expected": "revert" + } + ] + }, + { + "description": "User 1 reenables WETH as collateral", + "actions": [ + { + "name": "setUseAsCollateral", + "args": { + "reserve": "WETH", + "user": "1", + "useAsCollateral": "true" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-aave/helpers/scenarios/swap-rate-mode.json b/test-suites/test-aave/helpers/scenarios/swap-rate-mode.json new file mode 100644 index 00000000..137196cf --- /dev/null +++ b/test-suites/test-aave/helpers/scenarios/swap-rate-mode.json @@ -0,0 +1,167 @@ +{ + "title": "LendingPool: Swap rate mode", + "description": "Test cases for the swapBorrowRateMode() function.", + "stories": [ + { + "description": "User 0 tries to swap rate mode without any variable rate loan in progress (revert expected)", + "actions": [ + { + "name": "swapBorrowRateMode", + "args": { + "reserve": "DAI", + "user": "1", + "borrowRateMode": "variable" + }, + "expected": "revert", + "revertMessage": "User does not have a variable rate loan in progress on this reserve" + } + ] + }, + { + "description": "User 0 tries to swap rate mode without any stable rate loan in progress (revert expected)", + "actions": [ + { + "name": "swapBorrowRateMode", + "args": { + "reserve": "DAI", + "user": "1", + "borrowRateMode": "stable" + }, + "expected": "revert", + "revertMessage": "User does not have a stable rate loan in progress on this reserve" + } + ] + }, + { + "description": "User 0 deposits 1000 DAI, user 1 deposits 2 WETH as collateral, borrows 100 DAI at variable rate and swaps to stable after one year", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "2", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "2", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "swapBorrowRateMode", + "args": { + "reserve": "DAI", + "user": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 borrows another 100 DAI, and swaps back to variable after one year, repays the loan", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "swapBorrowRateMode", + "args": { + "reserve": "DAI", + "user": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 50 DAI to cover the interest", + "args": { + "reserve": "DAI", + "amount": "50", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-aave/helpers/scenarios/withdraw-negatives.json b/test-suites/test-aave/helpers/scenarios/withdraw-negatives.json new file mode 100644 index 00000000..fbc5c308 --- /dev/null +++ b/test-suites/test-aave/helpers/scenarios/withdraw-negatives.json @@ -0,0 +1,114 @@ +{ + "title": "LendingPool: Redeem negative test cases", + "description": "Redeem function.", + "stories": [ + { + "description": "Users 0 Deposits 1000 DAI and tries to redeem 0 DAI (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "0", + "user": "0" + }, + "expected": "revert", + "revertMessage": "Amount to redeem needs to be > 0" + } + ] + }, + { + "description": "Users 0 tries to redeem 1100 DAI from the 1000 DAI deposited (revert expected)", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "1100", + "user": "0" + }, + "expected": "revert", + "revertMessage": "User cannot redeem more than the available balance" + } + ] + }, + { + "description": "Users 1 deposits 1 WETH, borrows 100 DAI, tries to redeem the 1 WETH deposited (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "user": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "WETH", + "amount": "-1", + "user": "1" + }, + "expected": "revert", + "revertMessage": "Transfer cannot be allowed." + } + ] + } + ] +} diff --git a/test-suites/test-aave/helpers/scenarios/withdraw.json b/test-suites/test-aave/helpers/scenarios/withdraw.json new file mode 100644 index 00000000..19968ccc --- /dev/null +++ b/test-suites/test-aave/helpers/scenarios/withdraw.json @@ -0,0 +1,340 @@ +{ + "title": "LendingPool: withdraw", + "description": "withdraw function.", + "stories": [ + { + "description": "User 0 Deposits 1000 DAI in an empty reserve", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws half of the deposited DAI", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "500", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws remaining half of the deposited DAI", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 Deposits 1000 USDC in an empty reserve", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "USDC", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws half of the deposited USDC", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "USDC", + "amount": "500", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws remaining half of the deposited USDC", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "USDC", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 Deposits 1 WETH in an empty reserve", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws half of the deposited WETH", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "WETH", + "amount": "0.5", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws remaining half of the deposited WETH", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "WETH", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "Users 0 and 1 Deposit 1000 DAI, both withdraw", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "DAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "DAI", + "amount": "-1", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "Users 0 deposits 1000 DAI, user 1 Deposit 1000 USDC and 1 WETH, borrows 100 DAI. User 1 tries to withdraw all the USDC", + "actions": [ + { + "name": "deposit", + "args": { + "reserve": "DAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "USDC", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "USDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "DAI", + "amount": "100", + "user": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "USDC", + "amount": "-1", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "Users 1 tries to withdraw 0.05 WETH, which does not bring the HF below 1", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "WETH", + "amount": "0.05", + "user": "1" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-aave/helpers/utils/calculations.ts b/test-suites/test-aave/helpers/utils/calculations.ts new file mode 100644 index 00000000..fd6dea53 --- /dev/null +++ b/test-suites/test-aave/helpers/utils/calculations.ts @@ -0,0 +1,1434 @@ +import BigNumber from 'bignumber.js'; +import { ONE_YEAR, RAY, MAX_UINT_AMOUNT, PERCENTAGE_FACTOR } from '../../../../helpers/constants'; +import { + IReserveParams, + iAavePoolAssets, + RateMode, + tEthereumAddress, +} from '../../../../helpers/types'; +import './math'; +import { ReserveData, UserReserveData } from './interfaces'; + +export const strToBN = (amount: string): BigNumber => new BigNumber(amount); + +interface Configuration { + reservesParams: iAavePoolAssets; +} + +export const configuration: Configuration = {}; + +export const calcExpectedUserDataAfterDeposit = ( + amountDeposited: string, + reserveDataBeforeAction: ReserveData, + reserveDataAfterAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber, + currentTimestamp: BigNumber, + txCost: BigNumber +): UserReserveData => { + const expectedUserData = {}; + + expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; + expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt; + expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; + expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; + expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated; + + expectedUserData.liquidityRate = reserveDataAfterAction.liquidityRate; + + expectedUserData.scaledATokenBalance = calcExpectedScaledATokenBalance( + userDataBeforeAction, + reserveDataAfterAction.liquidityIndex, + new BigNumber(amountDeposited), + new BigNumber(0) + ); + expectedUserData.currentATokenBalance = calcExpectedATokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ).plus(amountDeposited); + + if (userDataBeforeAction.currentATokenBalance.eq(0)) { + expectedUserData.usageAsCollateralEnabled = true; + } else { + expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled; + } + + expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; + expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(amountDeposited); + + expectedUserData.currentStableDebt = expectedUserData.principalStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedUserData.currentVariableDebt = expectedUserData.principalStableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + return expectedUserData; +}; + +export const calcExpectedUserDataAfterWithdraw = ( + amountWithdrawn: string, + reserveDataBeforeAction: ReserveData, + reserveDataAfterAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber, + currentTimestamp: BigNumber, + txCost: BigNumber +): UserReserveData => { + const expectedUserData = {}; + + const aTokenBalance = calcExpectedATokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + if (amountWithdrawn == MAX_UINT_AMOUNT) { + amountWithdrawn = aTokenBalance.toFixed(0); + } + + expectedUserData.scaledATokenBalance = calcExpectedScaledATokenBalance( + userDataBeforeAction, + reserveDataAfterAction.liquidityIndex, + new BigNumber(0), + new BigNumber(amountWithdrawn) + ); + + expectedUserData.currentATokenBalance = aTokenBalance.minus(amountWithdrawn); + + expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; + expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt; + + expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; + expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; + expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated; + + expectedUserData.liquidityRate = reserveDataAfterAction.liquidityRate; + + if (userDataBeforeAction.currentATokenBalance.eq(0)) { + expectedUserData.usageAsCollateralEnabled = true; + } else { + //if the user is withdrawing everything, usageAsCollateralEnabled must be false + if (expectedUserData.currentATokenBalance.eq(0)) { + expectedUserData.usageAsCollateralEnabled = false; + } else { + expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled; + } + } + + expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountWithdrawn); + + return expectedUserData; +}; + +export const calcExpectedReserveDataAfterDeposit = ( + amountDeposited: string, + reserveDataBeforeAction: ReserveData, + txTimestamp: BigNumber +): ReserveData => { + const expectedReserveData: ReserveData = {}; + + expectedReserveData.address = reserveDataBeforeAction.address; + + expectedReserveData.totalLiquidity = new BigNumber(reserveDataBeforeAction.totalLiquidity).plus( + amountDeposited + ); + expectedReserveData.availableLiquidity = new BigNumber( + reserveDataBeforeAction.availableLiquidity + ).plus(amountDeposited); + + expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate; + expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( + reserveDataBeforeAction, + txTimestamp + ); + expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + expectedReserveData.totalVariableDebt = calcExpectedTotalVariableDebt( + reserveDataBeforeAction, + expectedReserveData.variableBorrowIndex + ); + + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; + expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt; + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + const rates = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + expectedReserveData.utilizationRate, + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.averageStableBorrowRate + ); + expectedReserveData.liquidityRate = rates[0]; + expectedReserveData.stableBorrowRate = rates[1]; + expectedReserveData.variableBorrowRate = rates[2]; + + return expectedReserveData; +}; + +export const calcExpectedReserveDataAfterWithdraw = ( + amountWithdrawn: string, + reserveDataBeforeAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber +): ReserveData => { + const expectedReserveData: ReserveData = {}; + + expectedReserveData.address = reserveDataBeforeAction.address; + + if (amountWithdrawn == MAX_UINT_AMOUNT) { + amountWithdrawn = calcExpectedATokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ).toFixed(); + } + + expectedReserveData.availableLiquidity = new BigNumber( + reserveDataBeforeAction.availableLiquidity + ).minus(amountWithdrawn); + + expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt; + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; + + expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( + reserveDataBeforeAction, + txTimestamp + ); + expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate; + + expectedReserveData.totalLiquidity = new BigNumber(reserveDataBeforeAction.availableLiquidity) + .minus(amountWithdrawn) + .plus(expectedReserveData.totalVariableDebt) + .plus(expectedReserveData.totalStableDebt); + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + const rates = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + expectedReserveData.utilizationRate, + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.averageStableBorrowRate + ); + expectedReserveData.liquidityRate = rates[0]; + expectedReserveData.stableBorrowRate = rates[1]; + expectedReserveData.variableBorrowRate = rates[2]; + + return expectedReserveData; +}; + +export const calcExpectedReserveDataAfterBorrow = ( + amountBorrowed: string, + borrowRateMode: string, + reserveDataBeforeAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber, + currentTimestamp: BigNumber +): ReserveData => { + const expectedReserveData = {}; + + expectedReserveData.address = reserveDataBeforeAction.address; + + const amountBorrowedBN = new BigNumber(amountBorrowed); + + expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity.minus( + amountBorrowedBN + ); + + expectedReserveData.lastUpdateTimestamp = txTimestamp; + + if (borrowRateMode == RateMode.Stable) { + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; + + const expectedVariableDebtAfterTx = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + const expectedStableDebtUntilTx = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + + expectedReserveData.principalStableDebt = expectedStableDebtUntilTx.plus(amountBorrowedBN); + + expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( + reserveDataBeforeAction.averageStableBorrowRate, + expectedStableDebtUntilTx, + amountBorrowedBN, + reserveDataBeforeAction.stableBorrowRate + ); + + const totalLiquidityAfterTx = expectedReserveData.availableLiquidity + .plus(expectedReserveData.principalStableDebt) + .plus(expectedVariableDebtAfterTx); + + const utilizationRateAfterTx = calcExpectedUtilizationRate( + expectedReserveData.principalStableDebt, //the expected principal debt is the total debt immediately after the tx + expectedVariableDebtAfterTx, + totalLiquidityAfterTx + ); + + const ratesAfterTx = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + utilizationRateAfterTx, + expectedReserveData.principalStableDebt, + expectedVariableDebtAfterTx, + expectedReserveData.averageStableBorrowRate + ); + + expectedReserveData.liquidityRate = ratesAfterTx[0]; + + expectedReserveData.stableBorrowRate = ratesAfterTx[1]; + + expectedReserveData.variableBorrowRate = ratesAfterTx[2]; + + expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( + expectedReserveData.principalStableDebt, + expectedReserveData.averageStableBorrowRate, + txTimestamp, + currentTimestamp + ); + + expectedReserveData.totalVariableDebt = reserveDataBeforeAction.scaledVariableDebt.rayMul( + calcExpectedReserveNormalizedDebt( + expectedReserveData.variableBorrowRate, + expectedReserveData.variableBorrowIndex, + txTimestamp, + currentTimestamp + ) + ); + + expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity + .plus(expectedReserveData.totalVariableDebt) + .plus(expectedReserveData.totalStableDebt); + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + } else { + expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt; + + const totalStableDebtAfterTx = calcExpectedStableDebtTokenBalance( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + + expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + currentTimestamp + ); + + expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate; + + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.plus( + amountBorrowedBN.rayDiv(expectedReserveData.variableBorrowIndex) + ); + + const totalVariableDebtAfterTx = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + const utilizationRateAfterTx = calcExpectedUtilizationRate( + totalStableDebtAfterTx, + totalVariableDebtAfterTx, + expectedReserveData.availableLiquidity + .plus(totalStableDebtAfterTx) + .plus(totalVariableDebtAfterTx) + ); + + const rates = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + utilizationRateAfterTx, + totalStableDebtAfterTx, + totalVariableDebtAfterTx, + expectedReserveData.averageStableBorrowRate + ); + + expectedReserveData.liquidityRate = rates[0]; + + expectedReserveData.stableBorrowRate = rates[1]; + + expectedReserveData.variableBorrowRate = rates[2]; + + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + calcExpectedReserveNormalizedDebt( + expectedReserveData.variableBorrowRate, + expectedReserveData.variableBorrowIndex, + txTimestamp, + currentTimestamp + ) + ); + + expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity + .plus(expectedReserveData.totalStableDebt) + .plus(expectedReserveData.totalVariableDebt); + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + } + + return expectedReserveData; +}; + +export const calcExpectedReserveDataAfterRepay = ( + amountRepaid: string, + borrowRateMode: RateMode, + reserveDataBeforeAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber, + currentTimestamp: BigNumber +): ReserveData => { + const expectedReserveData: ReserveData = {}; + + expectedReserveData.address = reserveDataBeforeAction.address; + + let amountRepaidBN = new BigNumber(amountRepaid); + + const userStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + const userVariableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + //if amount repaid == MAX_UINT_AMOUNT, user is repaying everything + if (amountRepaidBN.abs().eq(MAX_UINT_AMOUNT)) { + if (borrowRateMode == RateMode.Stable) { + amountRepaidBN = userStableDebt; + } else { + amountRepaidBN = userVariableDebt; + } + } + + expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( + reserveDataBeforeAction, + txTimestamp + ); + expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( + reserveDataBeforeAction, + txTimestamp + ); + + if (borrowRateMode == RateMode.Stable) { + const expectedDebt = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + + expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = expectedDebt.minus( + amountRepaidBN + ); + + //due to accumulation errors, the total stable debt might be smaller than the last user debt. + //in this case we simply set the total supply and avg stable rate to 0. + if (expectedReserveData.totalStableDebt.lt(0)) { + expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = expectedReserveData.averageStableBorrowRate = new BigNumber( + 0 + ); + } else { + expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( + reserveDataBeforeAction.averageStableBorrowRate, + expectedDebt, + amountRepaidBN.negated(), + userDataBeforeAction.stableBorrowRate + ); + + //also due to accumulation errors, the final avg stable rate when the last user repays might be negative. + //if that is the case, it means a small leftover of total stable debt is left, which can be erased. + + if (expectedReserveData.averageStableBorrowRate.lt(0)) { + expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = expectedReserveData.averageStableBorrowRate = new BigNumber( + 0 + ); + } + } + + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; + + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + } else { + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.minus( + amountRepaidBN.rayDiv(expectedReserveData.variableBorrowIndex) + ); + + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt; + expectedReserveData.totalStableDebt = reserveDataBeforeAction.totalStableDebt; + + expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate; + } + + expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity.plus( + amountRepaidBN + ); + + expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity + .plus(expectedReserveData.totalStableDebt) + .plus(expectedReserveData.totalVariableDebt); + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + + const rates = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + expectedReserveData.utilizationRate, + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.averageStableBorrowRate + ); + expectedReserveData.liquidityRate = rates[0]; + + expectedReserveData.stableBorrowRate = rates[1]; + + expectedReserveData.variableBorrowRate = rates[2]; + + expectedReserveData.lastUpdateTimestamp = txTimestamp; + + return expectedReserveData; +}; + +export const calcExpectedUserDataAfterBorrow = ( + amountBorrowed: string, + interestRateMode: string, + reserveDataBeforeAction: ReserveData, + expectedDataAfterAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber, + currentTimestamp: BigNumber +): UserReserveData => { + const expectedUserData = {}; + + const amountBorrowedBN = new BigNumber(amountBorrowed); + + if (interestRateMode == RateMode.Stable) { + const stableDebtUntilTx = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedUserData.principalStableDebt = stableDebtUntilTx.plus(amountBorrowed); + expectedUserData.stableRateLastUpdated = txTimestamp; + + expectedUserData.stableBorrowRate = calcExpectedUserStableRate( + stableDebtUntilTx, + userDataBeforeAction.stableBorrowRate, + amountBorrowedBN, + reserveDataBeforeAction.stableBorrowRate + ); + + expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance( + expectedUserData.principalStableDebt, + expectedUserData.stableBorrowRate, + txTimestamp, + currentTimestamp + ); + + expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt; + } else { + expectedUserData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.plus( + amountBorrowedBN.rayDiv(expectedDataAfterAction.variableBorrowIndex) + ); + + expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; + + expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; + + expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated; + + expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + currentTimestamp + ); + } + + expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( + expectedDataAfterAction, + expectedUserData, + currentTimestamp + ); + + expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; + + expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled; + + expectedUserData.currentATokenBalance = calcExpectedATokenBalance( + expectedDataAfterAction, + userDataBeforeAction, + currentTimestamp + ); + + expectedUserData.scaledATokenBalance = userDataBeforeAction.scaledATokenBalance; + + expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountBorrowed); + + return expectedUserData; +}; + +export const calcExpectedUserDataAfterRepay = ( + totalRepaid: string, + rateMode: RateMode, + reserveDataBeforeAction: ReserveData, + expectedDataAfterAction: ReserveData, + userDataBeforeAction: UserReserveData, + user: string, + onBehalfOf: string, + txTimestamp: BigNumber, + currentTimestamp: BigNumber +): UserReserveData => { + const expectedUserData = {}; + + const variableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + currentTimestamp + ); + + const stableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + currentTimestamp + ); + + let totalRepaidBN = new BigNumber(totalRepaid); + if (totalRepaidBN.abs().eq(MAX_UINT_AMOUNT)) { + totalRepaidBN = rateMode == RateMode.Stable ? stableDebt : variableDebt; + } + + if (rateMode == RateMode.Stable) { + expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt; + expectedUserData.currentVariableDebt = variableDebt; + + expectedUserData.principalStableDebt = expectedUserData.currentStableDebt = stableDebt.minus( + totalRepaidBN + ); + + if (expectedUserData.currentStableDebt.eq('0')) { + //user repaid everything + expectedUserData.stableBorrowRate = expectedUserData.stableRateLastUpdated = new BigNumber( + '0' + ); + } else { + expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; + expectedUserData.stableRateLastUpdated = txTimestamp; + } + } else { + expectedUserData.currentStableDebt = userDataBeforeAction.principalStableDebt; + expectedUserData.principalStableDebt = stableDebt; + expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; + expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated; + + expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt.minus( + totalRepaidBN.rayDiv(expectedDataAfterAction.variableBorrowIndex) + ); + expectedUserData.currentVariableDebt = expectedUserData.scaledVariableDebt.rayMul( + expectedDataAfterAction.variableBorrowIndex + ); + } + + expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; + + expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled; + + expectedUserData.currentATokenBalance = calcExpectedATokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + expectedUserData.scaledATokenBalance = userDataBeforeAction.scaledATokenBalance; + + if (user === onBehalfOf) { + expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(totalRepaidBN); + } else { + //wallet balance didn't change + expectedUserData.walletBalance = userDataBeforeAction.walletBalance; + } + + return expectedUserData; +}; + +export const calcExpectedUserDataAfterSetUseAsCollateral = ( + useAsCollateral: boolean, + reserveDataBeforeAction: ReserveData, + userDataBeforeAction: UserReserveData, + txCost: BigNumber +): UserReserveData => { + const expectedUserData = { ...userDataBeforeAction }; + + expectedUserData.usageAsCollateralEnabled = useAsCollateral; + + return expectedUserData; +}; + +export const calcExpectedReserveDataAfterSwapRateMode = ( + reserveDataBeforeAction: ReserveData, + userDataBeforeAction: UserReserveData, + rateMode: string, + txTimestamp: BigNumber +): ReserveData => { + const expectedReserveData: ReserveData = {}; + + expectedReserveData.address = reserveDataBeforeAction.address; + + const variableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + const stableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity; + + const totalStableDebtUntilTx = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + + if (rateMode === RateMode.Stable) { + //swap user stable debt to variable + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.plus( + stableDebt.rayDiv(expectedReserveData.variableBorrowIndex) + ); + + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = totalStableDebtUntilTx.minus( + stableDebt + ); + + expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( + reserveDataBeforeAction.averageStableBorrowRate, + expectedReserveData.principalStableDebt.plus(stableDebt), + stableDebt.negated(), + userDataBeforeAction.stableBorrowRate + ); + } else { + //swap variable to stable + + expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = totalStableDebtUntilTx.plus( + variableDebt + ); + + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.minus( + variableDebt.rayDiv(expectedReserveData.variableBorrowIndex) + ); + + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebt, + variableDebt, + reserveDataBeforeAction.stableBorrowRate + ); + } + + expectedReserveData.totalLiquidity = reserveDataBeforeAction.availableLiquidity + .plus(expectedReserveData.totalStableDebt) + .plus(expectedReserveData.totalVariableDebt); + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + + const rates = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + expectedReserveData.utilizationRate, + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.averageStableBorrowRate + ); + expectedReserveData.liquidityRate = rates[0]; + + expectedReserveData.stableBorrowRate = rates[1]; + + expectedReserveData.variableBorrowRate = rates[2]; + + return expectedReserveData; +}; + +export const calcExpectedUserDataAfterSwapRateMode = ( + reserveDataBeforeAction: ReserveData, + expectedDataAfterAction: ReserveData, + userDataBeforeAction: UserReserveData, + rateMode: string, + txCost: BigNumber, + txTimestamp: BigNumber +): UserReserveData => { + const expectedUserData = { ...userDataBeforeAction }; + + const stableDebtBalance = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + const variableDebtBalance = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + expectedUserData.currentATokenBalance = calcExpectedATokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + if (rateMode === RateMode.Stable) { + // swap to variable + expectedUserData.currentStableDebt = expectedUserData.principalStableDebt = new BigNumber(0); + + expectedUserData.stableBorrowRate = new BigNumber(0); + + expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt.plus( + stableDebtBalance.rayDiv(expectedDataAfterAction.variableBorrowIndex) + ); + expectedUserData.currentVariableDebt = expectedUserData.scaledVariableDebt.rayMul( + expectedDataAfterAction.variableBorrowIndex + ); + + expectedUserData.stableRateLastUpdated = new BigNumber(0); + } else { + expectedUserData.principalStableDebt = expectedUserData.currentStableDebt = userDataBeforeAction.currentStableDebt.plus( + variableDebtBalance + ); + + //weighted average of the previous and the current + expectedUserData.stableBorrowRate = calcExpectedUserStableRate( + stableDebtBalance, + userDataBeforeAction.stableBorrowRate, + variableDebtBalance, + reserveDataBeforeAction.stableBorrowRate + ); + + expectedUserData.stableRateLastUpdated = txTimestamp; + + expectedUserData.currentVariableDebt = expectedUserData.scaledVariableDebt = new BigNumber(0); + } + + expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; + + return expectedUserData; +}; + +export const calcExpectedReserveDataAfterStableRateRebalance = ( + reserveDataBeforeAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber +): ReserveData => { + const expectedReserveData: ReserveData = {}; + + expectedReserveData.address = reserveDataBeforeAction.address; + + const userStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + + expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity; + + expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity + .plus(expectedReserveData.totalStableDebt) + .plus(expectedReserveData.totalVariableDebt); + + //removing the stable liquidity at the old rate + + const avgRateBefore = calcExpectedAverageStableBorrowRateRebalance( + reserveDataBeforeAction.averageStableBorrowRate, + expectedReserveData.totalStableDebt, + userStableDebt.negated(), + userDataBeforeAction.stableBorrowRate + ); + // adding it again at the new rate + + expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRateRebalance( + avgRateBefore, + expectedReserveData.totalStableDebt.minus(userStableDebt), + userStableDebt, + reserveDataBeforeAction.stableBorrowRate + ); + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + + const rates = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + expectedReserveData.utilizationRate, + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.averageStableBorrowRate + ); + + expectedReserveData.liquidityRate = rates[0]; + + expectedReserveData.stableBorrowRate = rates[1]; + + expectedReserveData.variableBorrowRate = rates[2]; + + return expectedReserveData; +}; + +export const calcExpectedUserDataAfterStableRateRebalance = ( + reserveDataBeforeAction: ReserveData, + expectedDataAfterAction: ReserveData, + userDataBeforeAction: UserReserveData, + txCost: BigNumber, + txTimestamp: BigNumber +): UserReserveData => { + const expectedUserData = { ...userDataBeforeAction }; + + expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; + + expectedUserData.principalVariableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + expectedUserData.currentStableDebt = expectedUserData.principalStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + expectedUserData.stableRateLastUpdated = txTimestamp; + + expectedUserData.principalVariableDebt = userDataBeforeAction.principalVariableDebt; + + // Stable rate after burn + expectedUserData.stableBorrowRate = expectedDataAfterAction.averageStableBorrowRate; + expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; + + expectedUserData.currentATokenBalance = calcExpectedATokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + return expectedUserData; +}; + +const calcExpectedScaledATokenBalance = ( + userDataBeforeAction: UserReserveData, + index: BigNumber, + amountAdded: BigNumber, + amountTaken: BigNumber +) => { + return userDataBeforeAction.scaledATokenBalance + .plus(amountAdded.rayDiv(index)) + .minus(amountTaken.rayDiv(index)); +}; + +export const calcExpectedATokenBalance = ( + reserveData: ReserveData, + userData: UserReserveData, + currentTimestamp: BigNumber +) => { + const index = calcExpectedReserveNormalizedIncome(reserveData, currentTimestamp); + + const { scaledATokenBalance: scaledBalanceBeforeAction } = userData; + + return scaledBalanceBeforeAction.rayMul(index); +}; + +const calcExpectedAverageStableBorrowRate = ( + avgStableRateBefore: BigNumber, + totalStableDebtBefore: BigNumber, + amountChanged: string | BigNumber, + rate: BigNumber +) => { + const weightedTotalBorrows = avgStableRateBefore.multipliedBy(totalStableDebtBefore); + const weightedAmountBorrowed = rate.multipliedBy(amountChanged); + const totalBorrowedStable = totalStableDebtBefore.plus(amountChanged); + + if (totalBorrowedStable.eq(0)) return new BigNumber('0'); + + return weightedTotalBorrows + .plus(weightedAmountBorrowed) + .div(totalBorrowedStable) + .decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +const calcExpectedAverageStableBorrowRateRebalance = ( + avgStableRateBefore: BigNumber, + totalStableDebtBefore: BigNumber, + amountChanged: BigNumber, + rate: BigNumber +) => { + const weightedTotalBorrows = avgStableRateBefore.rayMul(totalStableDebtBefore); + const weightedAmountBorrowed = rate.rayMul(amountChanged.wadToRay()); + const totalBorrowedStable = totalStableDebtBefore.plus(amountChanged.wadToRay()); + + if (totalBorrowedStable.eq(0)) return new BigNumber('0'); + + return weightedTotalBorrows + .plus(weightedAmountBorrowed) + .rayDiv(totalBorrowedStable) + .decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +export const calcExpectedVariableDebtTokenBalance = ( + reserveData: ReserveData, + userData: UserReserveData, + currentTimestamp: BigNumber +) => { + const normalizedDebt = calcExpectedReserveNormalizedDebt( + reserveData.variableBorrowRate, + reserveData.variableBorrowIndex, + reserveData.lastUpdateTimestamp, + currentTimestamp + ); + + const { scaledVariableDebt } = userData; + + return scaledVariableDebt.rayMul(normalizedDebt); +}; + +export const calcExpectedStableDebtTokenBalance = ( + principalStableDebt: BigNumber, + stableBorrowRate: BigNumber, + stableRateLastUpdated: BigNumber, + currentTimestamp: BigNumber +) => { + if ( + stableBorrowRate.eq(0) || + currentTimestamp.eq(stableRateLastUpdated) || + stableRateLastUpdated.eq(0) + ) { + return principalStableDebt; + } + + const cumulatedInterest = calcCompoundedInterest( + stableBorrowRate, + currentTimestamp, + stableRateLastUpdated + ); + + return principalStableDebt.rayMul(cumulatedInterest); +}; + +const calcLinearInterest = ( + rate: BigNumber, + currentTimestamp: BigNumber, + lastUpdateTimestamp: BigNumber +) => { + const timeDifference = currentTimestamp.minus(lastUpdateTimestamp); + + const cumulatedInterest = rate + .multipliedBy(timeDifference) + .dividedBy(new BigNumber(ONE_YEAR)) + .plus(RAY); + + return cumulatedInterest; +}; + +const calcCompoundedInterest = ( + rate: BigNumber, + currentTimestamp: BigNumber, + lastUpdateTimestamp: BigNumber +) => { + const timeDifference = currentTimestamp.minus(lastUpdateTimestamp); + + if (timeDifference.eq(0)) { + return new BigNumber(RAY); + } + + const expMinusOne = timeDifference.minus(1); + const expMinusTwo = timeDifference.gt(2) ? timeDifference.minus(2) : 0; + + const ratePerSecond = rate.div(ONE_YEAR); + + const basePowerTwo = ratePerSecond.rayMul(ratePerSecond); + const basePowerThree = basePowerTwo.rayMul(ratePerSecond); + + const secondTerm = timeDifference.times(expMinusOne).times(basePowerTwo).div(2); + const thirdTerm = timeDifference + .times(expMinusOne) + .times(expMinusTwo) + .times(basePowerThree) + .div(6); + + return new BigNumber(RAY) + .plus(ratePerSecond.times(timeDifference)) + .plus(secondTerm) + .plus(thirdTerm); +}; + +export const calcExpectedInterestRates = ( + reserveSymbol: string, + marketStableRate: BigNumber, + utilizationRate: BigNumber, + totalStableDebt: BigNumber, + totalVariableDebt: BigNumber, + averageStableBorrowRate: BigNumber +): BigNumber[] => { + const { reservesParams } = configuration; + + const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol); + const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[ + reserveIndex + ]; + + let stableBorrowRate: BigNumber = marketStableRate; + let variableBorrowRate: BigNumber = new BigNumber(reserveConfiguration.baseVariableBorrowRate); + + const optimalRate = new BigNumber(reserveConfiguration.optimalUtilizationRate); + const excessRate = new BigNumber(RAY).minus(optimalRate); + if (utilizationRate.gt(optimalRate)) { + const excessUtilizationRateRatio = utilizationRate + .minus(reserveConfiguration.optimalUtilizationRate) + .rayDiv(excessRate); + + stableBorrowRate = stableBorrowRate + .plus(reserveConfiguration.stableRateSlope1) + .plus( + new BigNumber(reserveConfiguration.stableRateSlope2).rayMul(excessUtilizationRateRatio) + ); + + variableBorrowRate = variableBorrowRate + .plus(reserveConfiguration.variableRateSlope1) + .plus( + new BigNumber(reserveConfiguration.variableRateSlope2).rayMul(excessUtilizationRateRatio) + ); + } else { + stableBorrowRate = stableBorrowRate.plus( + new BigNumber(reserveConfiguration.stableRateSlope1).rayMul( + utilizationRate.rayDiv(new BigNumber(optimalRate)) + ) + ); + + variableBorrowRate = variableBorrowRate.plus( + utilizationRate + .rayDiv(optimalRate) + .rayMul(new BigNumber(reserveConfiguration.variableRateSlope1)) + ); + } + + const expectedOverallRate = calcExpectedOverallBorrowRate( + totalStableDebt, + totalVariableDebt, + variableBorrowRate, + averageStableBorrowRate + ); + const liquidityRate = expectedOverallRate + .rayMul(utilizationRate) + .percentMul(new BigNumber(PERCENTAGE_FACTOR).minus(reserveConfiguration.reserveFactor)); + + return [liquidityRate, stableBorrowRate, variableBorrowRate]; +}; + +export const calcExpectedOverallBorrowRate = ( + totalStableDebt: BigNumber, + totalVariableDebt: BigNumber, + currentVariableBorrowRate: BigNumber, + currentAverageStableBorrowRate: BigNumber +): BigNumber => { + const totalBorrows = totalStableDebt.plus(totalVariableDebt); + + if (totalBorrows.eq(0)) return strToBN('0'); + + const weightedVariableRate = totalVariableDebt.wadToRay().rayMul(currentVariableBorrowRate); + + const weightedStableRate = totalStableDebt.wadToRay().rayMul(currentAverageStableBorrowRate); + + const overallBorrowRate = weightedVariableRate + .plus(weightedStableRate) + .rayDiv(totalBorrows.wadToRay()); + + return overallBorrowRate; +}; + +export const calcExpectedUtilizationRate = ( + totalStableDebt: BigNumber, + totalVariableDebt: BigNumber, + totalLiquidity: BigNumber +): BigNumber => { + if (totalStableDebt.eq('0') && totalVariableDebt.eq('0')) { + return strToBN('0'); + } + + const utilization = totalStableDebt.plus(totalVariableDebt).rayDiv(totalLiquidity); + + return utilization; +}; + +const calcExpectedReserveNormalizedIncome = ( + reserveData: ReserveData, + currentTimestamp: BigNumber +) => { + const { liquidityRate, liquidityIndex, lastUpdateTimestamp } = reserveData; + + //if utilization rate is 0, nothing to compound + if (liquidityRate.eq('0')) { + return liquidityIndex; + } + + const cumulatedInterest = calcLinearInterest( + liquidityRate, + currentTimestamp, + lastUpdateTimestamp + ); + + const income = cumulatedInterest.rayMul(liquidityIndex); + + return income; +}; + +const calcExpectedReserveNormalizedDebt = ( + variableBorrowRate: BigNumber, + variableBorrowIndex: BigNumber, + lastUpdateTimestamp: BigNumber, + currentTimestamp: BigNumber +) => { + //if utilization rate is 0, nothing to compound + if (variableBorrowRate.eq('0')) { + return variableBorrowIndex; + } + + const cumulatedInterest = calcCompoundedInterest( + variableBorrowRate, + currentTimestamp, + lastUpdateTimestamp + ); + + const debt = cumulatedInterest.rayMul(variableBorrowIndex); + + return debt; +}; + +const calcExpectedUserStableRate = ( + balanceBefore: BigNumber, + rateBefore: BigNumber, + amount: BigNumber, + rateNew: BigNumber +) => { + return balanceBefore + .times(rateBefore) + .plus(amount.times(rateNew)) + .div(balanceBefore.plus(amount)); +}; + +const calcExpectedLiquidityIndex = (reserveData: ReserveData, timestamp: BigNumber) => { + //if utilization rate is 0, nothing to compound + if (reserveData.utilizationRate.eq('0')) { + return reserveData.liquidityIndex; + } + + const cumulatedInterest = calcLinearInterest( + reserveData.liquidityRate, + timestamp, + reserveData.lastUpdateTimestamp + ); + + return cumulatedInterest.rayMul(reserveData.liquidityIndex); +}; + +const calcExpectedVariableBorrowIndex = (reserveData: ReserveData, timestamp: BigNumber) => { + //if totalVariableDebt is 0, nothing to compound + if (reserveData.totalVariableDebt.eq('0')) { + return reserveData.variableBorrowIndex; + } + + const cumulatedInterest = calcCompoundedInterest( + reserveData.variableBorrowRate, + timestamp, + reserveData.lastUpdateTimestamp + ); + + return cumulatedInterest.rayMul(reserveData.variableBorrowIndex); +}; + +const calcExpectedTotalStableDebt = ( + principalStableDebt: BigNumber, + averageStableBorrowRate: BigNumber, + lastUpdateTimestamp: BigNumber, + currentTimestamp: BigNumber +) => { + const cumulatedInterest = calcCompoundedInterest( + averageStableBorrowRate, + currentTimestamp, + lastUpdateTimestamp + ); + + return cumulatedInterest.rayMul(principalStableDebt); +}; + +const calcExpectedTotalVariableDebt = ( + reserveData: ReserveData, + expectedVariableDebtIndex: BigNumber +) => { + return reserveData.scaledVariableDebt.rayMul(expectedVariableDebtIndex); +}; diff --git a/test-suites/test-aave/helpers/utils/helpers.ts b/test-suites/test-aave/helpers/utils/helpers.ts new file mode 100644 index 00000000..c38ce8e6 --- /dev/null +++ b/test-suites/test-aave/helpers/utils/helpers.ts @@ -0,0 +1,128 @@ +import { LendingPool } from '../../../../types/LendingPool'; +import { ReserveData, UserReserveData } from './interfaces'; +import { + getLendingRateOracle, + getIErc20Detailed, + getMintableERC20, + getAToken, + getStableDebtToken, + getVariableDebtToken, +} from '../../../../helpers/contracts-getters'; +import { tEthereumAddress } from '../../../../helpers/types'; +import BigNumber from 'bignumber.js'; +import { getDb, DRE } from '../../../../helpers/misc-utils'; +import { AaveProtocolDataProvider } from '../../../../types/AaveProtocolDataProvider'; + +export const getReserveData = async ( + helper: AaveProtocolDataProvider, + reserve: tEthereumAddress +): Promise => { + const [reserveData, tokenAddresses, rateOracle, token] = await Promise.all([ + helper.getReserveData(reserve), + helper.getReserveTokensAddresses(reserve), + getLendingRateOracle(), + getIErc20Detailed(reserve), + ]); + + const stableDebtToken = await getStableDebtToken(tokenAddresses.stableDebtTokenAddress); + const variableDebtToken = await getVariableDebtToken(tokenAddresses.variableDebtTokenAddress); + + const { 0: principalStableDebt } = await stableDebtToken.getSupplyData(); + const totalStableDebtLastUpdated = await stableDebtToken.getTotalSupplyLastUpdated(); + + const scaledVariableDebt = await variableDebtToken.scaledTotalSupply(); + + const rate = (await rateOracle.getMarketBorrowRate(reserve)).toString(); + const symbol = await token.symbol(); + const decimals = new BigNumber(await token.decimals()); + + const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) + .plus(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()); + + const utilizationRate = new BigNumber( + totalLiquidity.eq(0) + ? 0 + : new BigNumber(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()) + .rayDiv(totalLiquidity) + ); + + return { + totalLiquidity, + utilizationRate, + availableLiquidity: new BigNumber(reserveData.availableLiquidity.toString()), + totalStableDebt: new BigNumber(reserveData.totalStableDebt.toString()), + totalVariableDebt: new BigNumber(reserveData.totalVariableDebt.toString()), + liquidityRate: new BigNumber(reserveData.liquidityRate.toString()), + variableBorrowRate: new BigNumber(reserveData.variableBorrowRate.toString()), + stableBorrowRate: new BigNumber(reserveData.stableBorrowRate.toString()), + averageStableBorrowRate: new BigNumber(reserveData.averageStableBorrowRate.toString()), + liquidityIndex: new BigNumber(reserveData.liquidityIndex.toString()), + variableBorrowIndex: new BigNumber(reserveData.variableBorrowIndex.toString()), + lastUpdateTimestamp: new BigNumber(reserveData.lastUpdateTimestamp), + totalStableDebtLastUpdated: new BigNumber(totalStableDebtLastUpdated), + principalStableDebt: new BigNumber(principalStableDebt.toString()), + scaledVariableDebt: new BigNumber(scaledVariableDebt.toString()), + address: reserve, + aTokenAddress: tokenAddresses.aTokenAddress, + symbol, + decimals, + marketStableRate: new BigNumber(rate), + }; +}; + +export const getUserData = async ( + pool: LendingPool, + helper: AaveProtocolDataProvider, + reserve: string, + user: tEthereumAddress, + sender?: tEthereumAddress +): Promise => { + const [userData, scaledATokenBalance] = await Promise.all([ + helper.getUserReserveData(reserve, user), + getATokenUserData(reserve, user, helper), + ]); + + const token = await getMintableERC20(reserve); + const walletBalance = new BigNumber((await token.balanceOf(sender || user)).toString()); + + return { + scaledATokenBalance: new BigNumber(scaledATokenBalance), + currentATokenBalance: new BigNumber(userData.currentATokenBalance.toString()), + currentStableDebt: new BigNumber(userData.currentStableDebt.toString()), + currentVariableDebt: new BigNumber(userData.currentVariableDebt.toString()), + principalStableDebt: new BigNumber(userData.principalStableDebt.toString()), + scaledVariableDebt: new BigNumber(userData.scaledVariableDebt.toString()), + stableBorrowRate: new BigNumber(userData.stableBorrowRate.toString()), + liquidityRate: new BigNumber(userData.liquidityRate.toString()), + usageAsCollateralEnabled: userData.usageAsCollateralEnabled, + stableRateLastUpdated: new BigNumber(userData.stableRateLastUpdated.toString()), + walletBalance, + }; +}; + +export const getReserveAddressFromSymbol = async (symbol: string) => { + const token = await getMintableERC20( + (await getDb().get(`${symbol}.${DRE.network.name}`).value()).address + ); + + if (!token) { + throw `Could not find instance for contract ${symbol}`; + } + return token.address; +}; + +const getATokenUserData = async ( + reserve: string, + user: string, + helpersContract: AaveProtocolDataProvider +) => { + const aTokenAddress: string = (await helpersContract.getReserveTokensAddresses(reserve)) + .aTokenAddress; + + const aToken = await getAToken(aTokenAddress); + + const scaledBalance = await aToken.scaledBalanceOf(user); + return scaledBalance.toString(); +}; diff --git a/test-suites/test-aave/helpers/utils/interfaces/index.ts b/test-suites/test-aave/helpers/utils/interfaces/index.ts new file mode 100644 index 00000000..17660fcc --- /dev/null +++ b/test-suites/test-aave/helpers/utils/interfaces/index.ts @@ -0,0 +1,40 @@ +import BigNumber from 'bignumber.js'; + +export interface UserReserveData { + scaledATokenBalance: BigNumber; + currentATokenBalance: BigNumber; + currentStableDebt: BigNumber; + currentVariableDebt: BigNumber; + principalStableDebt: BigNumber; + scaledVariableDebt: BigNumber; + liquidityRate: BigNumber; + stableBorrowRate: BigNumber; + stableRateLastUpdated: BigNumber; + usageAsCollateralEnabled: Boolean; + walletBalance: BigNumber; + [key: string]: BigNumber | string | Boolean; +} + +export interface ReserveData { + address: string; + symbol: string; + decimals: BigNumber; + totalLiquidity: BigNumber; + availableLiquidity: BigNumber; + totalStableDebt: BigNumber; + totalVariableDebt: BigNumber; + principalStableDebt: BigNumber; + scaledVariableDebt: BigNumber; + averageStableBorrowRate: BigNumber; + variableBorrowRate: BigNumber; + stableBorrowRate: BigNumber; + utilizationRate: BigNumber; + liquidityIndex: BigNumber; + variableBorrowIndex: BigNumber; + aTokenAddress: string; + marketStableRate: BigNumber; + lastUpdateTimestamp: BigNumber; + totalStableDebtLastUpdated: BigNumber; + liquidityRate: BigNumber; + [key: string]: BigNumber | string; +} diff --git a/test-suites/test-aave/helpers/utils/math.ts b/test-suites/test-aave/helpers/utils/math.ts new file mode 100644 index 00000000..27ea0531 --- /dev/null +++ b/test-suites/test-aave/helpers/utils/math.ts @@ -0,0 +1,97 @@ +import BigNumber from 'bignumber.js'; +import { + RAY, + WAD, + HALF_RAY, + HALF_WAD, + WAD_RAY_RATIO, + HALF_PERCENTAGE, + PERCENTAGE_FACTOR, +} from '../../../../helpers/constants'; + +declare module 'bignumber.js' { + interface BigNumber { + ray: () => BigNumber; + wad: () => BigNumber; + halfRay: () => BigNumber; + halfWad: () => BigNumber; + halfPercentage: () => BigNumber; + wadMul: (a: BigNumber) => BigNumber; + wadDiv: (a: BigNumber) => BigNumber; + rayMul: (a: BigNumber) => BigNumber; + rayDiv: (a: BigNumber) => BigNumber; + percentMul: (a: BigNumber) => BigNumber; + percentDiv: (a: BigNumber) => BigNumber; + rayToWad: () => BigNumber; + wadToRay: () => BigNumber; + } +} + +BigNumber.prototype.ray = (): BigNumber => { + return new BigNumber(RAY).decimalPlaces(0); +}; +BigNumber.prototype.wad = (): BigNumber => { + return new BigNumber(WAD).decimalPlaces(0); +}; + +BigNumber.prototype.halfRay = (): BigNumber => { + return new BigNumber(HALF_RAY).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.halfWad = (): BigNumber => { + return new BigNumber(HALF_WAD).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.wadMul = function (b: BigNumber): BigNumber { + return this.halfWad().plus(this.multipliedBy(b)).div(WAD).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.wadDiv = function (a: BigNumber): BigNumber { + const halfA = a.div(2).decimalPlaces(0, BigNumber.ROUND_DOWN); + + return halfA.plus(this.multipliedBy(WAD)).div(a).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.rayMul = function (a: BigNumber): BigNumber { + return this.halfRay().plus(this.multipliedBy(a)).div(RAY).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.rayDiv = function (a: BigNumber): BigNumber { + const halfA = a.div(2).decimalPlaces(0, BigNumber.ROUND_DOWN); + + return halfA + .plus(this.multipliedBy(RAY)) + .decimalPlaces(0, BigNumber.ROUND_DOWN) + .div(a) + .decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.rayToWad = function (): BigNumber { + const halfRatio = new BigNumber(WAD_RAY_RATIO).div(2); + + return halfRatio.plus(this).div(WAD_RAY_RATIO).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.wadToRay = function (): BigNumber { + return this.multipliedBy(WAD_RAY_RATIO).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.halfPercentage = (): BigNumber => { + return new BigNumber(HALF_PERCENTAGE).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.percentMul = function (b: BigNumber): BigNumber { + return this.halfPercentage() + .plus(this.multipliedBy(b)) + .div(PERCENTAGE_FACTOR) + .decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.percentDiv = function (a: BigNumber): BigNumber { + const halfA = a.div(2).decimalPlaces(0, BigNumber.ROUND_DOWN); + + return halfA + .plus(this.multipliedBy(PERCENTAGE_FACTOR)) + .div(a) + .decimalPlaces(0, BigNumber.ROUND_DOWN); +}; diff --git a/test-suites/test-aave/lending-pool-addresses-provider.spec.ts b/test-suites/test-aave/lending-pool-addresses-provider.spec.ts new file mode 100644 index 00000000..0f7630f9 --- /dev/null +++ b/test-suites/test-aave/lending-pool-addresses-provider.spec.ts @@ -0,0 +1,101 @@ +import { expect } from 'chai'; +import { createRandomAddress } from '../../helpers/misc-utils'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +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-deployments'; + +const { utils } = ethers; + +makeSuite('LendingPoolAddressesProvider', (testEnv: TestEnv) => { + it('Test the accessibility of the LendingPoolAddressesProvider', async () => { + const { addressesProvider, users } = testEnv; + const mockAddress = createRandomAddress(); + const { INVALID_OWNER_REVERT_MSG } = ProtocolErrors; + + await addressesProvider.transferOwnership(users[1].address); + + for (const contractFunction of [ + addressesProvider.setMarketId, + addressesProvider.setLendingPoolImpl, + addressesProvider.setLendingPoolConfiguratorImpl, + addressesProvider.setLendingPoolCollateralManager, + addressesProvider.setPoolAdmin, + addressesProvider.setPriceOracle, + addressesProvider.setLendingRateOracle, + ]) { + await expect(contractFunction(mockAddress)).to.be.revertedWith(INVALID_OWNER_REVERT_MSG); + } + + await expect( + addressesProvider.setAddress(utils.keccak256(utils.toUtf8Bytes('RANDOM_ID')), mockAddress) + ).to.be.revertedWith(INVALID_OWNER_REVERT_MSG); + + await expect( + addressesProvider.setAddressAsProxy( + utils.keccak256(utils.toUtf8Bytes('RANDOM_ID')), + mockAddress + ) + ).to.be.revertedWith(INVALID_OWNER_REVERT_MSG); + }); + + it('Tests adding a proxied address with `setAddressAsProxy()`', async () => { + const { addressesProvider, users } = testEnv; + const { INVALID_OWNER_REVERT_MSG } = ProtocolErrors; + + const currentAddressesProviderOwner = users[1]; + + const mockLendingPool = await deployLendingPool(); + const proxiedAddressId = utils.keccak256(utils.toUtf8Bytes('RANDOM_PROXIED')); + + const proxiedAddressSetReceipt = await waitForTx( + await addressesProvider + .connect(currentAddressesProviderOwner.signer) + .setAddressAsProxy(proxiedAddressId, mockLendingPool.address) + ); + + if (!proxiedAddressSetReceipt.events || proxiedAddressSetReceipt.events?.length < 1) { + throw new Error('INVALID_EVENT_EMMITED'); + } + + expect(proxiedAddressSetReceipt.events[0].event).to.be.equal('ProxyCreated'); + expect(proxiedAddressSetReceipt.events[1].event).to.be.equal('AddressSet'); + expect(proxiedAddressSetReceipt.events[1].args?.id).to.be.equal(proxiedAddressId); + expect(proxiedAddressSetReceipt.events[1].args?.newAddress).to.be.equal( + mockLendingPool.address + ); + expect(proxiedAddressSetReceipt.events[1].args?.hasProxy).to.be.equal(true); + }); + + it('Tests adding a non proxied address with `setAddress()`', async () => { + const { addressesProvider, users } = testEnv; + const { INVALID_OWNER_REVERT_MSG } = ProtocolErrors; + + const currentAddressesProviderOwner = users[1]; + const mockNonProxiedAddress = createRandomAddress(); + const nonProxiedAddressId = utils.keccak256(utils.toUtf8Bytes('RANDOM_NON_PROXIED')); + + const nonProxiedAddressSetReceipt = await waitForTx( + await addressesProvider + .connect(currentAddressesProviderOwner.signer) + .setAddress(nonProxiedAddressId, mockNonProxiedAddress) + ); + + expect(mockNonProxiedAddress.toLowerCase()).to.be.equal( + (await addressesProvider.getAddress(nonProxiedAddressId)).toLowerCase() + ); + + if (!nonProxiedAddressSetReceipt.events || nonProxiedAddressSetReceipt.events?.length < 1) { + throw new Error('INVALID_EVENT_EMMITED'); + } + + expect(nonProxiedAddressSetReceipt.events[0].event).to.be.equal('AddressSet'); + expect(nonProxiedAddressSetReceipt.events[0].args?.id).to.be.equal(nonProxiedAddressId); + expect(nonProxiedAddressSetReceipt.events[0].args?.newAddress).to.be.equal( + mockNonProxiedAddress + ); + expect(nonProxiedAddressSetReceipt.events[0].args?.hasProxy).to.be.equal(false); + }); +}); diff --git a/test-suites/test-aave/liquidation-atoken.spec.ts b/test-suites/test-aave/liquidation-atoken.spec.ts new file mode 100644 index 00000000..1b6f9911 --- /dev/null +++ b/test-suites/test-aave/liquidation-atoken.spec.ts @@ -0,0 +1,379 @@ +import BigNumber from 'bignumber.js'; + +import { DRE } from '../../helpers/misc-utils'; +import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { makeSuite } from './helpers/make-suite'; +import { ProtocolErrors, RateMode } from '../../helpers/types'; +import { calcExpectedVariableDebtTokenBalance } from './helpers/utils/calculations'; +import { getUserData, getReserveData } from './helpers/utils/helpers'; + +const chai = require('chai'); +const { expect } = chai; + +makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) => { + const { + LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD, + INVALID_HF, + LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER, + LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED, + LP_IS_PAUSED, + } = ProtocolErrors; + + it('Deposits WETH, borrows DAI/Check liquidation fails because health factor is above 1', async () => { + const { dai, weth, users, pool, oracle } = testEnv; + const depositor = users[0]; + const borrower = users[1]; + + //mints DAI to depositor + await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access depositor wallet + await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 1 deposits 1000 DAI + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + await pool + .connect(depositor.signer) + .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); + + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(amountETHtoDeposit); + + //approve protocol to access borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 2 deposits 1 WETH + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 2 borrows + const userGlobalData = await pool.getUserAccountData(borrower.address); + const daiPrice = await oracle.getAssetPrice(dai.address); + + const amountDAIToBorrow = await convertToCurrencyDecimals( + dai.address, + new BigNumber(userGlobalData.availableBorrowsETH.toString()) + .div(daiPrice.toString()) + .multipliedBy(0.95) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(dai.address, amountDAIToBorrow, RateMode.Variable, '0', borrower.address); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.bignumber.equal( + '8250', + 'Invalid liquidation threshold' + ); + + //someone tries to liquidate user 2 + await expect( + pool.liquidationCall(weth.address, dai.address, borrower.address, 1, true) + ).to.be.revertedWith(LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD); + }); + + it('Drop the health factor below 1', async () => { + const { dai, users, pool, oracle } = testEnv; + const borrower = users[1]; + + const daiPrice = await oracle.getAssetPrice(dai.address); + + await oracle.setAssetPrice( + dai.address, + new BigNumber(daiPrice.toString()).multipliedBy(1.15).toFixed(0) + ); + + const userGlobalData = await pool.getUserAccountData(borrower.address); + + expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( + oneEther.toString(), + INVALID_HF + ); + }); + + it('Tries to liquidate a different currency than the loan principal', async () => { + const { pool, users, weth } = testEnv; + const borrower = users[1]; + //user 2 tries to borrow + await expect( + pool.liquidationCall(weth.address, weth.address, borrower.address, oneEther.toString(), true) + ).revertedWith(LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER); + }); + + it('Tries to liquidate a different collateral than the borrower collateral', async () => { + const { pool, dai, users } = testEnv; + const borrower = users[1]; + + await expect( + pool.liquidationCall(dai.address, dai.address, borrower.address, oneEther.toString(), true) + ).revertedWith(LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED); + }); + + it('Liquidates the borrow', async () => { + const { pool, dai, weth, aWETH, aDai, users, oracle, helpersContract, deployer } = testEnv; + const borrower = users[1]; + + //mints dai to the caller + + await dai.mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access depositor wallet + await dai.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const daiReserveDataBefore = await getReserveData(helpersContract, dai.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const amountToLiquidate = new BigNumber(userReserveDataBefore.currentVariableDebt.toString()) + .div(2) + .toFixed(0); + + const tx = await pool.liquidationCall( + weth.address, + dai.address, + borrower.address, + amountToLiquidate, + true + ); + + const userReserveDataAfter = await helpersContract.getUserReserveData( + dai.address, + borrower.address + ); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); + const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + + const collateralPrice = (await oracle.getAssetPrice(weth.address)).toString(); + const principalPrice = (await oracle.getAssetPrice(dai.address)).toString(); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(dai.address) + ).decimals.toString(); + + const expectedCollateralLiquidated = new BigNumber(principalPrice) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals))) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + if (!tx.blockNumber) { + expect(false, 'Invalid block number'); + return; + } + + const txTimestamp = new BigNumber( + (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp + ); + + const variableDebtBeforeTx = calcExpectedVariableDebtTokenBalance( + daiReserveDataBefore, + userReserveDataBefore, + txTimestamp + ); + + expect(userGlobalDataAfter.healthFactor.toString()).to.be.bignumber.gt( + oneEther.toFixed(0), + 'Invalid health factor' + ); + + expect(userReserveDataAfter.currentVariableDebt.toString()).to.be.bignumber.almostEqual( + new BigNumber(variableDebtBeforeTx).minus(amountToLiquidate).toFixed(0), + 'Invalid user borrow balance after liquidation' + ); + + expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(daiReserveDataBefore.availableLiquidity.toString()) + .plus(amountToLiquidate) + .toFixed(0), + 'Invalid principal available liquidity' + ); + + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( + daiReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + daiReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + + expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(ethReserveDataBefore.availableLiquidity.toString()).toFixed(0), + 'Invalid collateral available liquidity' + ); + + expect( + (await helpersContract.getUserReserveData(weth.address, deployer.address)) + .usageAsCollateralEnabled + ).to.be.true; + }); + + it('User 3 deposits 1000 USDC, user 4 1 WETH, user 4 borrows - drops HF, liquidates the borrow', async () => { + const { users, pool, usdc, oracle, weth, helpersContract } = testEnv; + const depositor = users[3]; + const borrower = users[4]; + + //mints USDC to depositor + await usdc + .connect(depositor.signer) + .mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 3 deposits 1000 USDC + const amountUSDCtoDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(usdc.address, amountUSDCtoDeposit, depositor.address, '0'); + + //user 4 deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(amountETHtoDeposit); + + //approve protocol to access borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 4 borrows + const userGlobalData = await pool.getUserAccountData(borrower.address); + + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const amountUSDCToBorrow = await convertToCurrencyDecimals( + usdc.address, + new BigNumber(userGlobalData.availableBorrowsETH.toString()) + .div(usdcPrice.toString()) + .multipliedBy(0.9502) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); + + //drops HF below 1 + + await oracle.setAssetPrice( + usdc.address, + new BigNumber(usdcPrice.toString()).multipliedBy(1.12).toFixed(0) + ); + + //mints dai to the liquidator + + await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const userReserveDataBefore = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + + const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .multipliedBy(0.5) + .toFixed(0); + + await pool.liquidationCall( + weth.address, + usdc.address, + borrower.address, + amountToLiquidate, + true + ); + + const userReserveDataAfter = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + const usdcReserveDataAfter = await helpersContract.getReserveData(usdc.address); + const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + + const collateralPrice = (await oracle.getAssetPrice(weth.address)).toString(); + const principalPrice = (await oracle.getAssetPrice(usdc.address)).toString(); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(usdc.address) + ).decimals.toString(); + + const expectedCollateralLiquidated = new BigNumber(principalPrice) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals))) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + expect(userGlobalDataAfter.healthFactor.toString()).to.be.bignumber.gt( + oneEther.toFixed(0), + 'Invalid health factor' + ); + + expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( + new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .minus(amountToLiquidate) + .toFixed(0), + 'Invalid user borrow balance after liquidation' + ); + + expect(usdcReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(usdcReserveDataBefore.availableLiquidity.toString()) + .plus(amountToLiquidate) + .toFixed(0), + 'Invalid principal available liquidity' + ); + + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(usdcReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( + usdcReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(usdcReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + usdcReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + + expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(ethReserveDataBefore.availableLiquidity.toString()).toFixed(0), + 'Invalid collateral available liquidity' + ); + }); +}); diff --git a/test-suites/test-aave/liquidation-underlying.spec.ts b/test-suites/test-aave/liquidation-underlying.spec.ts new file mode 100644 index 00000000..b0951ce3 --- /dev/null +++ b/test-suites/test-aave/liquidation-underlying.spec.ts @@ -0,0 +1,492 @@ +import BigNumber from 'bignumber.js'; + +import { DRE, increaseTime } from '../../helpers/misc-utils'; +import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { makeSuite } from './helpers/make-suite'; +import { ProtocolErrors, RateMode } from '../../helpers/types'; +import { calcExpectedStableDebtTokenBalance } from './helpers/utils/calculations'; +import { getUserData } from './helpers/utils/helpers'; +import { CommonsConfig } from '../../markets/aave/commons'; + +import { parseEther } from 'ethers/lib/utils'; + +const chai = require('chai'); + +const { expect } = chai; + +makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', (testEnv) => { + const { INVALID_HF } = ProtocolErrors; + + before('Before LendingPool liquidation: set config', () => { + BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); + }); + + after('After LendingPool liquidation: reset config', () => { + BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); + }); + + it("It's not possible to liquidate on a non-active collateral or a non active principal", async () => { + const { configurator, weth, pool, users, dai } = testEnv; + const user = users[1]; + await configurator.deactivateReserve(weth.address); + + await expect( + pool.liquidationCall(weth.address, dai.address, user.address, parseEther('1000'), false) + ).to.be.revertedWith('2'); + + await configurator.activateReserve(weth.address); + + await configurator.deactivateReserve(dai.address); + + await expect( + pool.liquidationCall(weth.address, dai.address, user.address, parseEther('1000'), false) + ).to.be.revertedWith('2'); + + await configurator.activateReserve(dai.address); + }); + + it('Deposits WETH, borrows DAI', async () => { + const { dai, weth, users, pool, oracle } = testEnv; + const depositor = users[0]; + const borrower = users[1]; + + //mints DAI to depositor + await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access depositor wallet + await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 1 deposits 1000 DAI + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); + //user 2 deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); + + //approve protocol to access the borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 2 borrows + + const userGlobalData = await pool.getUserAccountData(borrower.address); + const daiPrice = await oracle.getAssetPrice(dai.address); + + const amountDAIToBorrow = await convertToCurrencyDecimals( + dai.address, + new BigNumber(userGlobalData.availableBorrowsETH.toString()) + .div(daiPrice.toString()) + .multipliedBy(0.95) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.bignumber.equal( + '8250', + INVALID_HF + ); + }); + + it('Drop the health factor below 1', async () => { + const { dai, weth, users, pool, oracle } = testEnv; + const borrower = users[1]; + + const daiPrice = await oracle.getAssetPrice(dai.address); + + await oracle.setAssetPrice( + dai.address, + new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0) + ); + + const userGlobalData = await pool.getUserAccountData(borrower.address); + + expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( + oneEther.toFixed(0), + INVALID_HF + ); + }); + + it('Liquidates the borrow', async () => { + const { dai, weth, users, pool, oracle, helpersContract } = testEnv; + const liquidator = users[3]; + const borrower = users[1]; + + //mints dai to the liquidator + await dai.connect(liquidator.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access the liquidator wallet + await dai.connect(liquidator.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + + await increaseTime(100); + + const tx = await pool + .connect(liquidator.signer) + .liquidationCall(weth.address, dai.address, borrower.address, amountToLiquidate, false); + + const userReserveDataAfter = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); + const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + + const collateralPrice = await oracle.getAssetPrice(weth.address); + const principalPrice = await oracle.getAssetPrice(dai.address); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(dai.address) + ).decimals.toString(); + + const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div( + new BigNumber(collateralPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div(100) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + if (!tx.blockNumber) { + expect(false, 'Invalid block number'); + return; + } + const txTimestamp = new BigNumber( + (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp + ); + + const stableDebtBeforeTx = calcExpectedStableDebtTokenBalance( + userReserveDataBefore.principalStableDebt, + userReserveDataBefore.stableBorrowRate, + userReserveDataBefore.stableRateLastUpdated, + txTimestamp + ); + + expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( + stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), + 'Invalid user debt after liquidation' + ); + + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( + daiReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + daiReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + + expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(daiReserveDataBefore.availableLiquidity.toString()) + .plus(amountToLiquidate) + .toFixed(0), + 'Invalid principal available liquidity' + ); + + expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) + .minus(expectedCollateralLiquidated) + .toFixed(0), + 'Invalid collateral available liquidity' + ); + }); + + it('User 3 deposits 1000 USDC, user 4 1 WETH, user 4 borrows - drops HF, liquidates the borrow', async () => { + const { usdc, users, pool, oracle, weth, helpersContract } = testEnv; + + const depositor = users[3]; + const borrower = users[4]; + const liquidator = users[5]; + + //mints USDC to depositor + await usdc + .connect(depositor.signer) + .mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //depositor deposits 1000 USDC + const amountUSDCtoDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(usdc.address, amountUSDCtoDeposit, depositor.address, '0'); + + //borrower deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); + + //approve protocol to access the borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //borrower borrows + const userGlobalData = await pool.getUserAccountData(borrower.address); + + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const amountUSDCToBorrow = await convertToCurrencyDecimals( + usdc.address, + new BigNumber(userGlobalData.availableBorrowsETH.toString()) + .div(usdcPrice.toString()) + .multipliedBy(0.9502) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); + + //drops HF below 1 + await oracle.setAssetPrice( + usdc.address, + new BigNumber(usdcPrice.toString()).multipliedBy(1.12).toFixed(0) + ); + + //mints dai to the liquidator + + await usdc + .connect(liquidator.signer) + .mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.connect(liquidator.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const userReserveDataBefore = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + + const amountToLiquidate = DRE.ethers.BigNumber.from( + userReserveDataBefore.currentStableDebt.toString() + ) + .div(2) + .toString(); + + await pool + .connect(liquidator.signer) + .liquidationCall(weth.address, usdc.address, borrower.address, amountToLiquidate, false); + + const userReserveDataAfter = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + const usdcReserveDataAfter = await helpersContract.getReserveData(usdc.address); + const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + + const collateralPrice = await oracle.getAssetPrice(weth.address); + const principalPrice = await oracle.getAssetPrice(usdc.address); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(usdc.address) + ).decimals.toString(); + + const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div( + new BigNumber(collateralPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div(100) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + expect(userGlobalDataAfter.healthFactor.toString()).to.be.bignumber.gt( + oneEther.toFixed(0), + 'Invalid health factor' + ); + + expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( + new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .minus(amountToLiquidate) + .toFixed(0), + 'Invalid user borrow balance after liquidation' + ); + + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(usdcReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( + usdcReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(usdcReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + usdcReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + + expect(usdcReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(usdcReserveDataBefore.availableLiquidity.toString()) + .plus(amountToLiquidate) + .toFixed(0), + 'Invalid principal available liquidity' + ); + + expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) + .minus(expectedCollateralLiquidated) + .toFixed(0), + 'Invalid collateral available liquidity' + ); + }); + + it('User 4 deposits 10 AAVE - drops HF, liquidates the AAVE, which results on a lower amount being liquidated', async () => { + const { aave, usdc, users, pool, oracle, helpersContract } = testEnv; + + const depositor = users[3]; + const borrower = users[4]; + const liquidator = users[5]; + + //mints AAVE to borrower + await aave.connect(borrower.signer).mint(await convertToCurrencyDecimals(aave.address, '10')); + + //approve protocol to access the borrower wallet + await aave.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //borrower deposits 10 AAVE + const amountToDeposit = await convertToCurrencyDecimals(aave.address, '10'); + + await pool + .connect(borrower.signer) + .deposit(aave.address, amountToDeposit, borrower.address, '0'); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + //drops HF below 1 + await oracle.setAssetPrice( + usdc.address, + new BigNumber(usdcPrice.toString()).multipliedBy(1.14).toFixed(0) + ); + + //mints usdc to the liquidator + await usdc + .connect(liquidator.signer) + .mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.connect(liquidator.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const userReserveDataBefore = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address); + const aaveReserveDataBefore = await helpersContract.getReserveData(aave.address); + + const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .div(2) + .decimalPlaces(0, BigNumber.ROUND_DOWN) + .toFixed(0); + + const collateralPrice = await oracle.getAssetPrice(aave.address); + const principalPrice = await oracle.getAssetPrice(usdc.address); + + await pool + .connect(liquidator.signer) + .liquidationCall(aave.address, usdc.address, borrower.address, amountToLiquidate, false); + + const userReserveDataAfter = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + const usdcReserveDataAfter = await helpersContract.getReserveData(usdc.address); + const aaveReserveDataAfter = await helpersContract.getReserveData(aave.address); + + const aaveConfiguration = await helpersContract.getReserveConfigurationData(aave.address); + const collateralDecimals = aaveConfiguration.decimals.toString(); + const liquidationBonus = aaveConfiguration.liquidationBonus.toString(); + + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(usdc.address) + ).decimals.toString(); + + const expectedCollateralLiquidated = oneEther.multipliedBy('10'); + + const expectedPrincipal = new BigNumber(collateralPrice.toString()) + .times(expectedCollateralLiquidated) + .times(new BigNumber(10).pow(principalDecimals)) + .div( + new BigNumber(principalPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .times(10000) + .div(liquidationBonus.toString()) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + expect(userGlobalDataAfter.healthFactor.toString()).to.be.bignumber.gt( + oneEther.toFixed(0), + 'Invalid health factor' + ); + + expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( + new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .minus(expectedPrincipal) + .toFixed(0), + 'Invalid user borrow balance after liquidation' + ); + + expect(usdcReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(usdcReserveDataBefore.availableLiquidity.toString()) + .plus(expectedPrincipal) + .toFixed(0), + 'Invalid principal available liquidity' + ); + + expect(aaveReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(aaveReserveDataBefore.availableLiquidity.toString()) + .minus(expectedCollateralLiquidated) + .toFixed(0), + 'Invalid collateral available liquidity' + ); + }); +}); diff --git a/test-suites/test-aave/mainnet/check-list.spec.ts b/test-suites/test-aave/mainnet/check-list.spec.ts new file mode 100644 index 00000000..a741dab4 --- /dev/null +++ b/test-suites/test-aave/mainnet/check-list.spec.ts @@ -0,0 +1,366 @@ +import { MAX_UINT_AMOUNT } from '../../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../../helpers/contracts-helpers'; +import { makeSuite, TestEnv } from '../helpers/make-suite'; +import { parseEther } from 'ethers/lib/utils'; +import { DRE, waitForTx } from '../../../helpers/misc-utils'; +import { BigNumber } from 'ethers'; +import { getStableDebtToken, getVariableDebtToken } from '../../../helpers/contracts-getters'; +import { deploySelfdestructTransferMock } from '../../../helpers/contracts-deployments'; +import { IUniswapV2Router02Factory } from '../../../types/IUniswapV2Router02Factory'; + +const { expect } = require('chai'); + +const UNISWAP_ROUTER = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'; + +makeSuite('Mainnet Check list', (testEnv: TestEnv) => { + const zero = BigNumber.from('0'); + const depositSize = parseEther('5'); + const daiSize = parseEther('10000'); + it('Deposit WETH', async () => { + const { users, wethGateway, aWETH, pool } = testEnv; + + const user = users[1]; + + // Deposit with native ETH + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(depositSize); + }); + + it('Withdraw WETH - Partial', async () => { + const { users, wethGateway, aWETH, pool } = testEnv; + + const user = users[1]; + const priorEthersBalance = await user.signer.getBalance(); + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.'); + + // Partially withdraw native ETH + const partialWithdraw = await convertToCurrencyDecimals(aWETH.address, '2'); + + // Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether + const approveTx = await aWETH + .connect(user.signer) + .approve(wethGateway.address, MAX_UINT_AMOUNT); + const { gasUsed: approveGas } = await waitForTx(approveTx); + + // Partial Withdraw and send native Ether to user + const { gasUsed: withdrawGas } = await waitForTx( + await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) + ); + + const afterPartialEtherBalance = await user.signer.getBalance(); + const afterPartialATokensBalance = await aWETH.balanceOf(user.address); + const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice); + + expect(afterPartialEtherBalance).to.be.equal( + priorEthersBalance.add(partialWithdraw).sub(gasCosts), + 'User ETHER balance should contain the partial withdraw' + ); + expect(afterPartialATokensBalance).to.be.equal( + aTokensBalance.sub(partialWithdraw), + 'User aWETH balance should be substracted' + ); + }); + + it('Withdraw WETH - Full', async () => { + const { users, aWETH, wethGateway, pool } = testEnv; + + const user = users[1]; + const priorEthersBalance = await user.signer.getBalance(); + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.'); + + // Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether + const approveTx = await aWETH + .connect(user.signer) + .approve(wethGateway.address, MAX_UINT_AMOUNT); + const { gasUsed: approveGas } = await waitForTx(approveTx); + + // Full withdraw + const { gasUsed: withdrawGas } = await waitForTx( + await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) + ); + + const afterFullEtherBalance = await user.signer.getBalance(); + const afterFullATokensBalance = await aWETH.balanceOf(user.address); + const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice); + + expect(afterFullEtherBalance).to.be.eq( + priorEthersBalance.add(aTokensBalance).sub(gasCosts), + 'User ETHER balance should contain the full withdraw' + ); + expect(afterFullATokensBalance).to.be.eq(0, 'User aWETH balance should be zero'); + }); + + it('Borrow stable WETH and Full Repay with ETH', async () => { + const { users, wethGateway, aWETH, dai, aDai, weth, pool, helpersContract } = testEnv; + const borrowSize = parseEther('1'); + const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); + const user = users[1]; + + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const stableDebtToken = await getStableDebtToken(stableDebtTokenAddress); + + // Deposit 10000 DAI + await dai.connect(user.signer).mint(daiSize); + await dai.connect(user.signer).approve(pool.address, daiSize); + await pool.connect(user.signer).deposit(dai.address, daiSize, user.address, '0'); + + const aTokensBalance = await aDai.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(daiSize); + + // Borrow WETH with WETH as collateral + await waitForTx( + await pool.connect(user.signer).borrow(weth.address, borrowSize, '1', '0', user.address) + ); + + const debtBalance = await stableDebtToken.balanceOf(user.address); + + expect(debtBalance).to.be.gt(zero); + + // Full Repay WETH with native ETH + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) + ); + + const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); + expect(debtBalanceAfterRepay).to.be.eq(zero); + }); + + it('Borrow variable WETH and Full Repay with ETH', async () => { + const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; + const borrowSize = parseEther('1'); + const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); + const user = users[1]; + + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + // Deposit with native ETH + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(depositSize); + + // Borrow WETH with WETH as collateral + await waitForTx( + await pool.connect(user.signer).borrow(weth.address, borrowSize, '2', '0', user.address) + ); + + const debtBalance = await varDebtToken.balanceOf(user.address); + + expect(debtBalance).to.be.gt(zero); + + // Partial Repay WETH loan with native ETH + const partialPayment = repaySize.div(2); + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(partialPayment, '2', user.address, { value: partialPayment }) + ); + + const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); + expect(debtBalanceAfterPartialRepay).to.be.lt(debtBalance); + + // Full Repay WETH loan with native ETH + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) + ); + const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); + expect(debtBalanceAfterFullRepay).to.be.eq(zero); + }); + + it('Borrow ETH via delegateApprove ETH and repays back', async () => { + const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; + const borrowSize = parseEther('1'); + const user = users[2]; + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + const priorDebtBalance = await varDebtToken.balanceOf(user.address); + expect(priorDebtBalance).to.be.eq(zero); + + // Deposit WETH with native ETH + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(depositSize); + + // Delegates borrowing power of WETH to WETHGateway + await waitForTx( + await varDebtToken.connect(user.signer).approveDelegation(wethGateway.address, borrowSize) + ); + + // Borrows ETH with WETH as collateral + await waitForTx(await wethGateway.connect(user.signer).borrowETH(borrowSize, '2', '0')); + + const debtBalance = await varDebtToken.balanceOf(user.address); + + expect(debtBalance).to.be.gt(zero); + + // Full Repay WETH loan with native ETH + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) + ); + const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); + expect(debtBalanceAfterFullRepay).to.be.eq(zero); + }); + + it('Should revert if receiver function receives Ether if not WETH', async () => { + const { users, wethGateway } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + + // Call receiver function (empty data + value) + await expect( + user.signer.sendTransaction({ + to: wethGateway.address, + value: amount, + gasLimit: DRE.network.config.gas, + }) + ).to.be.revertedWith('Receive not allowed'); + }); + + it('Should revert if fallback functions is called with Ether', async () => { + const { users, wethGateway } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + const fakeABI = ['function wantToCallFallback()']; + const abiCoder = new DRE.ethers.utils.Interface(fakeABI); + const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []); + + // Call fallback function with value + await expect( + user.signer.sendTransaction({ + to: wethGateway.address, + data: fakeMethodEncoded, + value: amount, + gasLimit: DRE.network.config.gas, + }) + ).to.be.revertedWith('Fallback not allowed'); + }); + + it('Should revert if fallback functions is called', async () => { + const { users, wethGateway } = testEnv; + const user = users[0]; + + const fakeABI = ['function wantToCallFallback()']; + const abiCoder = new DRE.ethers.utils.Interface(fakeABI); + const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []); + + // Call fallback function without value + await expect( + user.signer.sendTransaction({ + to: wethGateway.address, + data: fakeMethodEncoded, + gasLimit: DRE.network.config.gas, + }) + ).to.be.revertedWith('Fallback not allowed'); + }); + + it('Getters should retrieve correct state', async () => { + const { aWETH, weth, pool, wethGateway } = testEnv; + + const WETHAddress = await wethGateway.getWETHAddress(); + const aWETHAddress = await wethGateway.getAWETHAddress(); + const poolAddress = await wethGateway.getLendingPoolAddress(); + + expect(WETHAddress).to.be.equal(weth.address); + expect(aWETHAddress).to.be.equal(aWETH.address); + expect(poolAddress).to.be.equal(pool.address); + }); + + it('Owner can do emergency token recovery', async () => { + const { users, weth, dai, wethGateway, deployer } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + + const uniswapRouter = IUniswapV2Router02Factory.connect(UNISWAP_ROUTER, user.signer); + await uniswapRouter.swapETHForExactTokens( + amount, // 1 DAI + [weth.address, dai.address], // Uniswap paths WETH - DAI + user.address, + (await DRE.ethers.provider.getBlock('latest')).timestamp + 300, + { + value: amount, // 1 Ether, we get refund of the unneeded Ether to buy 1 DAI + } + ); + const daiBalanceAfterMint = await dai.balanceOf(user.address); + + await dai.connect(user.signer).transfer(wethGateway.address, amount); + const daiBalanceAfterBadTransfer = await dai.balanceOf(user.address); + expect(daiBalanceAfterBadTransfer).to.be.eq( + daiBalanceAfterMint.sub(amount), + 'User should have lost the funds here.' + ); + + await wethGateway + .connect(deployer.signer) + .emergencyTokenTransfer(dai.address, user.address, amount); + const daiBalanceAfterRecovery = await dai.balanceOf(user.address); + + expect(daiBalanceAfterRecovery).to.be.eq( + daiBalanceAfterMint, + 'User should recover the funds due emergency token transfer' + ); + }); + + it('Owner can do emergency native ETH recovery', async () => { + const { users, wethGateway, deployer } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + const userBalancePriorCall = await user.signer.getBalance(); + + // Deploy contract with payable selfdestruct contract + const selfdestructContract = await deploySelfdestructTransferMock(); + + // Selfdestruct the mock, pointing to WETHGateway address + const callTx = await selfdestructContract + .connect(user.signer) + .destroyAndTransfer(wethGateway.address, { value: amount }); + const { gasUsed } = await waitForTx(callTx); + const gasFees = gasUsed.mul(callTx.gasPrice); + const userBalanceAfterCall = await user.signer.getBalance(); + + expect(userBalanceAfterCall).to.be.eq(userBalancePriorCall.sub(amount).sub(gasFees), ''); + ('User should have lost the funds'); + + // Recover the funds from the contract and sends back to the user + await wethGateway.connect(deployer.signer).emergencyEtherTransfer(user.address, amount); + + const userBalanceAfterRecovery = await user.signer.getBalance(); + const wethGatewayAfterRecovery = await DRE.ethers.provider.getBalance(wethGateway.address); + + expect(userBalanceAfterRecovery).to.be.eq( + userBalancePriorCall.sub(gasFees), + 'User should recover the funds due emergency eth transfer.' + ); + expect(wethGatewayAfterRecovery).to.be.eq('0', 'WETHGateway ether balance should be zero.'); + }); +}); diff --git a/test-suites/test-aave/pausable-functions.spec.ts b/test-suites/test-aave/pausable-functions.spec.ts new file mode 100644 index 00000000..c95aaf3c --- /dev/null +++ b/test-suites/test-aave/pausable-functions.spec.ts @@ -0,0 +1,330 @@ +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors, RateMode } from '../../helpers/types'; +import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../../helpers/constants'; +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'); + +makeSuite('Pausable Pool', (testEnv: TestEnv) => { + let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver; + + const { + LP_IS_PAUSED, + INVALID_FROM_BALANCE_AFTER_TRANSFER, + INVALID_TO_BALANCE_AFTER_TRANSFER, + } = ProtocolErrors; + + before(async () => { + _mockFlashLoanReceiver = await getMockFlashLoanReceiver(); + }); + + it('User 0 deposits 1000 DAI. Configurator pauses pool. Transfers to user 1 reverts. Configurator unpauses the network and next transfer succees', async () => { + const { users, pool, dai, aDai, configurator } = testEnv; + + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await dai.connect(users[0].signer).mint(amountDAItoDeposit); + + // user 0 deposits 1000 DAI + await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool + .connect(users[0].signer) + .deposit(dai.address, amountDAItoDeposit, users[0].address, '0'); + + const user0Balance = await aDai.balanceOf(users[0].address); + const user1Balance = await aDai.balanceOf(users[1].address); + + // Configurator pauses the pool + await configurator.connect(users[1].signer).setPoolPause(true); + + // User 0 tries the transfer to User 1 + await expect( + aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit) + ).to.revertedWith(LP_IS_PAUSED); + + const pausedFromBalance = await aDai.balanceOf(users[0].address); + const pausedToBalance = await aDai.balanceOf(users[1].address); + + expect(pausedFromBalance).to.be.equal( + user0Balance.toString(), + INVALID_TO_BALANCE_AFTER_TRANSFER + ); + expect(pausedToBalance.toString()).to.be.equal( + user1Balance.toString(), + INVALID_FROM_BALANCE_AFTER_TRANSFER + ); + + // Configurator unpauses the pool + await configurator.connect(users[1].signer).setPoolPause(false); + + // User 0 succeeds transfer to User 1 + await aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit); + + const fromBalance = await aDai.balanceOf(users[0].address); + const toBalance = await aDai.balanceOf(users[1].address); + + expect(fromBalance.toString()).to.be.equal( + user0Balance.sub(amountDAItoDeposit), + INVALID_FROM_BALANCE_AFTER_TRANSFER + ); + expect(toBalance.toString()).to.be.equal( + user1Balance.add(amountDAItoDeposit), + INVALID_TO_BALANCE_AFTER_TRANSFER + ); + }); + + it('Deposit', async () => { + const { users, pool, dai, aDai, configurator } = testEnv; + + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await dai.connect(users[0].signer).mint(amountDAItoDeposit); + + // user 0 deposits 1000 DAI + await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + // Configurator pauses the pool + await configurator.connect(users[1].signer).setPoolPause(true); + await expect( + pool.connect(users[0].signer).deposit(dai.address, amountDAItoDeposit, users[0].address, '0') + ).to.revertedWith(LP_IS_PAUSED); + + // Configurator unpauses the pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('Withdraw', async () => { + const { users, pool, dai, aDai, configurator } = testEnv; + + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await dai.connect(users[0].signer).mint(amountDAItoDeposit); + + // user 0 deposits 1000 DAI + await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool + .connect(users[0].signer) + .deposit(dai.address, amountDAItoDeposit, users[0].address, '0'); + + // Configurator pauses the pool + await configurator.connect(users[1].signer).setPoolPause(true); + + // user tries to burn + await expect( + pool.connect(users[0].signer).withdraw(dai.address, amountDAItoDeposit, users[0].address) + ).to.revertedWith(LP_IS_PAUSED); + + // Configurator unpauses the pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('Borrow', async () => { + const { pool, dai, users, configurator } = testEnv; + + const user = users[1]; + // Pause the pool + await configurator.connect(users[1].signer).setPoolPause(true); + + // Try to execute liquidation + await expect( + pool.connect(user.signer).borrow(dai.address, '1', '1', '0', user.address) + ).revertedWith(LP_IS_PAUSED); + + // Unpause the pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('Repay', async () => { + const { pool, dai, users, configurator } = testEnv; + + const user = users[1]; + // Pause the pool + await configurator.connect(users[1].signer).setPoolPause(true); + + // Try to execute liquidation + await expect(pool.connect(user.signer).repay(dai.address, '1', '1', user.address)).revertedWith( + LP_IS_PAUSED + ); + + // Unpause the pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('Flash loan', async () => { + const { dai, pool, weth, users, configurator } = testEnv; + + const caller = users[3]; + + const flashAmount = parseEther('0.8'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + // Pause pool + await configurator.connect(users[1].signer).setPoolPause(true); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [flashAmount], + [1], + caller.address, + '0x10', + '0' + ) + ).revertedWith(LP_IS_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('Liquidation call', async () => { + const { users, pool, usdc, oracle, weth, configurator, helpersContract } = testEnv; + const depositor = users[3]; + const borrower = users[4]; + + //mints USDC to depositor + await usdc + .connect(depositor.signer) + .mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 3 deposits 1000 USDC + const amountUSDCtoDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(usdc.address, amountUSDCtoDeposit, depositor.address, '0'); + + //user 4 deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(amountETHtoDeposit); + + //approve protocol to access borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 4 borrows + const userGlobalData = await pool.getUserAccountData(borrower.address); + + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const amountUSDCToBorrow = await convertToCurrencyDecimals( + usdc.address, + new BigNumber(userGlobalData.availableBorrowsETH.toString()) + .div(usdcPrice.toString()) + .multipliedBy(0.9502) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); + + // Drops HF below 1 + await oracle.setAssetPrice( + usdc.address, + new BigNumber(usdcPrice.toString()).multipliedBy(1.2).toFixed(0) + ); + + //mints dai to the liquidator + await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000')); + await usdc.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const userReserveDataBefore = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .multipliedBy(0.5) + .toFixed(0); + + // Pause pool + await configurator.connect(users[1].signer).setPoolPause(true); + + // Do liquidation + await expect( + pool.liquidationCall(weth.address, usdc.address, borrower.address, amountToLiquidate, true) + ).revertedWith(LP_IS_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('SwapBorrowRateMode', async () => { + const { pool, weth, dai, usdc, users, configurator } = testEnv; + const user = users[1]; + const amountWETHToDeposit = parseEther('10'); + const amountDAIToDeposit = parseEther('120'); + const amountToBorrow = parseUnits('65', 6); + + await weth.connect(user.signer).mint(amountWETHToDeposit); + await weth.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool.connect(user.signer).deposit(weth.address, amountWETHToDeposit, user.address, '0'); + + await dai.connect(user.signer).mint(amountDAIToDeposit); + await dai.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool.connect(user.signer).deposit(dai.address, amountDAIToDeposit, user.address, '0'); + + await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0, user.address); + + // Pause pool + await configurator.connect(users[1].signer).setPoolPause(true); + + // Try to repay + await expect( + pool.connect(user.signer).swapBorrowRateMode(usdc.address, RateMode.Stable) + ).revertedWith(LP_IS_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('RebalanceStableBorrowRate', async () => { + const { pool, dai, users, configurator } = testEnv; + const user = users[1]; + // Pause pool + await configurator.connect(users[1].signer).setPoolPause(true); + + await expect( + pool.connect(user.signer).rebalanceStableBorrowRate(dai.address, user.address) + ).revertedWith(LP_IS_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('setUserUseReserveAsCollateral', async () => { + const { pool, weth, users, configurator } = testEnv; + const user = users[1]; + + const amountWETHToDeposit = parseEther('1'); + await weth.connect(user.signer).mint(amountWETHToDeposit); + await weth.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool.connect(user.signer).deposit(weth.address, amountWETHToDeposit, user.address, '0'); + + // Pause pool + await configurator.connect(users[1].signer).setPoolPause(true); + + await expect( + pool.connect(user.signer).setUserUseReserveAsCollateral(weth.address, false) + ).revertedWith(LP_IS_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); +}); diff --git a/test-suites/test-aave/pool-modifiers.spec.ts b/test-suites/test-aave/pool-modifiers.spec.ts new file mode 100644 index 00000000..fb915b15 --- /dev/null +++ b/test-suites/test-aave/pool-modifiers.spec.ts @@ -0,0 +1,241 @@ +// import {iATokenBase, iAssetsWithoutETH, ITestEnvWithoutInstances, RateMode} from '../utils/types'; +// import { +// LendingPoolConfiguratorInstance, +// LendingPoolInstance, +// ATokenInstance, +// LendingPoolCoreInstance, +// MintableERC20Instance, +// } from '../utils/typechain-types/truffle-contracts'; +// import {testEnvProviderWithoutInstances} from '../utils/truffle/dlp-tests-env'; +// import {oneEther, ETHEREUM_ADDRESS} from '../utils/constants'; +// import {convertToCurrencyDecimals} from '../utils/misc-utils'; + +// const expectRevert = require('@openzeppelin/test-helpers').expectRevert; + +// contract('LendingPool: Modifiers', async ([deployer, ...users]) => { +// let _testEnvProvider: ITestEnvWithoutInstances; +// let _lendingPoolConfiguratorInstance: LendingPoolConfiguratorInstance; +// let _lendingPoolInstance: LendingPoolInstance; +// let _lendingPoolCoreInstance: LendingPoolCoreInstance; +// let _aTokenInstances: iATokenBase; +// let _tokenInstances: iAssetsWithoutETH; + +// before('Initializing LendingPool test variables', async () => { +// console.time('setup-test'); +// _testEnvProvider = await testEnvProviderWithoutInstances(artifacts, [deployer, ...users]); + +// const { +// getAllAssetsInstances, +// getLendingPoolInstance, +// getLendingPoolCoreInstance, +// getLendingPoolConfiguratorInstance, +// getATokenInstances, +// } = _testEnvProvider; +// const instances = await Promise.all([ +// getLendingPoolInstance(), +// getLendingPoolCoreInstance(), +// getLendingPoolConfiguratorInstance(), +// getATokenInstances(), +// getAllAssetsInstances(), +// ]); + +// _lendingPoolInstance = instances[0]; +// _lendingPoolCoreInstance = instances[1]; +// _lendingPoolConfiguratorInstance = instances[2]; + +// _aTokenInstances = instances[3]; +// _tokenInstances = instances[4]; +// console.timeEnd('setup-test'); +// }); + +// it('Tries to deposit in an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.deposit(deployer, '1', '0'), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to invoke redeemUnderlying on an reserve, from a non-aToken address', async () => { +// await expectRevert( +// _lendingPoolInstance.redeemUnderlying(ETHEREUM_ADDRESS, deployer, '1', '0'), +// 'The caller of this function can only be the aToken contract of this reserve' +// ); +// }); + +// it('Tries to borrow from an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.borrow(deployer, '1', '0', RateMode.Stable), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to repay in an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.repay(deployer, '1', deployer), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to swapBorrowRateMode on an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.swapBorrowRateMode(deployer), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to rebalanceStableBorrowRate on an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.rebalanceStableBorrowRate(deployer, deployer), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to setUserUseReserveAsCollateral on an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.setUserUseReserveAsCollateral(deployer, true), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to invoke liquidationCall on an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.liquidationCall(ETHEREUM_ADDRESS, deployer, deployer, '1', false), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to invoke liquidationCall on an inactive collateral', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.liquidationCall(deployer, ETHEREUM_ADDRESS, deployer, '1', false), +// 'Action requires an active reserve' +// ); +// }); + +// it('Freezes the ETH reserve', async () => { +// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS); +// }); + +// it('tries to deposit in a freezed reserve', async () => { +// await expectRevert( +// _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, '1', '0'), +// 'Action requires an unfreezed reserve' +// ); +// }); + +// it('tries to borrow from a freezed reserve', async () => { +// await expectRevert( +// _lendingPoolInstance.borrow(ETHEREUM_ADDRESS, '1', '0', '0'), +// 'Action requires an unfreezed reserve' +// ); +// }); + +// it('tries to swap interest rate mode in a freezed reserve', async () => { +// await expectRevert( +// _lendingPoolInstance.swapBorrowRateMode(ETHEREUM_ADDRESS), +// 'Action requires an unfreezed reserve' +// ); +// }); + +// it('tries to disable as collateral a freezed reserve', async () => { +// await expectRevert( +// _lendingPoolInstance.setUserUseReserveAsCollateral(ETHEREUM_ADDRESS, false), +// 'Action requires an unfreezed reserve' +// ); +// }); + +// it('unfreezes the reserve, user deposits 1 ETH, freezes the reserve, check that the user can redeem', async () => { +// const {aWETH} = _aTokenInstances; + +// //unfreezes the reserve +// await _lendingPoolConfiguratorInstance.unfreezeReserve(ETHEREUM_ADDRESS); + +// //deposit 1 ETH +// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, oneEther, '0', { +// value: oneEther.toString(), +// }); + +// //freezes the reserve +// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS); + +// const balance = await aWETH.balanceOf(deployer); + +// await aWETH.redeem(balance); +// }); + +// it('unfreezes the reserve, user 0 deposits 100 DAI, user 1 deposits 1 ETH and borrows 50 DAI, freezes the reserve, checks that the user 1 can repay', async () => { +// const {aWETH, aDAI} = _aTokenInstances; +// const {DAI} = _tokenInstances; + +// //unfreezes the reserve +// await _lendingPoolConfiguratorInstance.unfreezeReserve(ETHEREUM_ADDRESS); + +// const amountDAI = await convertToCurrencyDecimals(DAI.address, '100'); + +// //user 0 deposits 100 DAI +// await DAI.mint(amountDAI, {from: users[0]}); + +// await DAI.approve(_lendingPoolCoreInstance.address, amountDAI, {from: users[0]}); + +// await _lendingPoolInstance.deposit(DAI.address, amountDAI, '0', {from: users[0]}); + +// //user 1 deposits 1 ETH +// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, oneEther, '0', { +// from: users[1], +// value: oneEther.toString(), +// }); + +// const amountDAIToBorrow = await convertToCurrencyDecimals(DAI.address, '10'); + +// //user 1 borrows 10 DAI +// await _lendingPoolInstance.borrow(DAI.address, amountDAIToBorrow, RateMode.Stable, '0', { +// from: users[1], +// }); + +// //freezes the reserve +// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS); + +// //user 1 repays 1 DAI +// await DAI.approve(_lendingPoolCoreInstance.address, amountDAIToBorrow, {from: users[1]}); + +// await _lendingPoolInstance.repay(DAI.address, oneEther, users[1], {from: users[1]}); +// }); + +// it('Check that liquidationCall can be executed on a freezed reserve', async () => { +// const {aWETH, aDAI} = _aTokenInstances; +// const {DAI} = _tokenInstances; + +// //user 2 tries to liquidate + +// await expectRevert( +// _lendingPoolInstance.liquidationCall( +// ETHEREUM_ADDRESS, +// DAI.address, +// users[1], +// oneEther, +// true, +// {from: users[2]} +// ), +// 'Health factor is not below the threshold' +// ); +// }); + +// it('Check that rebalanceStableBorrowRate can be executed on a freezed reserve', async () => { +// const {aWETH, aDAI} = _aTokenInstances; +// const {DAI} = _tokenInstances; + +// //user 2 tries to liquidate + +// await expectRevert( +// _lendingPoolInstance.rebalanceStableBorrowRate(DAI.address, users[1]), +// 'Interest rate rebalance conditions were not met' +// ); +// }); +// }); diff --git a/test-suites/test-aave/rate-strategy.spec.ts b/test-suites/test-aave/rate-strategy.spec.ts new file mode 100644 index 00000000..b56c754e --- /dev/null +++ b/test-suites/test-aave/rate-strategy.spec.ts @@ -0,0 +1,165 @@ +// import { +// IReserveParams, +// iAavePoolAssets, +// iAssetsWithoutETH, +// ITestEnvWithoutInstances, +// } from "../utils/types" +// import { + +// LendingPoolAddressesProviderInstance, + +// DefaultReserveInterestRateStrategyInstance, +// MintableERC20Instance, +// } from "../utils/typechain-types/truffle-contracts" +// import { testEnvProviderWithoutInstances} from "../utils/truffle/dlp-tests-env" +// import {RAY} from "../utils/constants" +// import BigNumber from "bignumber.js" + +// const {expect} = require("chai") + +// contract("Interest rate strategy", async ([deployer, ...users]) => { +// let _testEnvProvider: ITestEnvWithoutInstances +// let _strategyInstance: DefaultReserveInterestRateStrategyInstance +// let _tokenInstances: iAssetsWithoutETH +// let _addressesProviderInstance: LendingPoolAddressesProviderInstance +// let _reservesParams: iAavePoolAssets + +// before("Initializing test variables", async () => { +// console.time('setup-test'); +// _testEnvProvider = await testEnvProviderWithoutInstances( +// artifacts, +// [deployer, ...users], +// ) + +// const { +// getAllAssetsInstances, +// getLendingPoolAddressesProviderInstance, +// getAavePoolReservesParams, +// } = _testEnvProvider + +// const instances = await Promise.all([ +// getAllAssetsInstances(), +// getLendingPoolAddressesProviderInstance() +// ]) + +// _tokenInstances = instances[0] +// _addressesProviderInstance = instances[1] +// _reservesParams = await getAavePoolReservesParams() +// console.timeEnd('setup-test'); +// }) + +// it("Deploys a new instance of a DefaultReserveInterestRateStrategy contract", async () => { +// const {DAI: daiInstance} = _tokenInstances + +// const {DAI: daiConfiguration} = _reservesParams + +// const contract: any = await artifacts.require("DefaultReserveInterestRateStrategy") +// const mathLibrary = await artifacts.require("WadRayMath") +// const mathLibraryInstance = await mathLibrary.new() + +// await contract.link("WadRayMath", mathLibraryInstance.address) + +// _strategyInstance = await contract.new( +// daiInstance.address, +// _addressesProviderInstance.address, +// daiConfiguration.baseVariableBorrowRate, +// daiConfiguration.variableRateSlope1, +// daiConfiguration.variableRateSlope2, +// daiConfiguration.stableRateSlope1, +// daiConfiguration.stableRateSlope2, +// ) +// }) + +// it("Checks rates at 0% utilization rate", async () => { +// const {DAI: daiInstance} = _tokenInstances +// const {DAI: daiConfiguration} = _reservesParams +// const data: any = await _strategyInstance.calculateInterestRates( +// daiInstance.address, +// "1000000000000000000", +// "0", +// "0", +// "0", +// ) + +// expect(data.currentLiquidityRate.toString()).to.be.equal("0", "Invalid liquidity rate") +// expect(data.currentStableBorrowRate.toString()).to.be.equal( +// new BigNumber(0.039).times(RAY).toFixed(0), +// "Invalid stable rate", +// ) +// expect(data.currentVariableBorrowRate.toString()).to.be.equal( +// daiConfiguration.baseVariableBorrowRate, +// "Invalid variable rate", +// ) +// }) + +// it("Checks rates at 80% utilization rate", async () => { +// const {DAI: daiInstance} = _tokenInstances +// const {DAI: daiConfiguration} = _reservesParams +// const data: any = await _strategyInstance.calculateInterestRates( +// daiInstance.address, +// "200000000000000000", +// "0", +// "800000000000000000", +// "0", +// ) + +// const expectedVariableRate = new BigNumber(daiConfiguration.baseVariableBorrowRate) +// .plus(daiConfiguration.variableRateSlope1) + +// expect(data.currentLiquidityRate.toString()).to.be.equal( +// expectedVariableRate.times(0.8).toFixed(0), +// "Invalid liquidity rate", +// ) + +// expect(data.currentVariableBorrowRate.toString()).to.be.equal( +// new BigNumber(daiConfiguration.baseVariableBorrowRate) +// .plus(daiConfiguration.variableRateSlope1) +// .toFixed(0), +// "Invalid variable rate", +// ) + +// expect(data.currentStableBorrowRate.toString()).to.be.equal( +// new BigNumber(0.039) +// .times(RAY) +// .plus(daiConfiguration.stableRateSlope1) +// .toFixed(0), +// "Invalid stable rate", +// ) +// }) + +// it("Checks rates at 100% utilization rate", async () => { +// const {DAI: daiInstance} = _tokenInstances +// const {DAI: daiConfiguration} = _reservesParams +// const data: any = await _strategyInstance.calculateInterestRates( +// daiInstance.address, +// "0", +// "0", +// "1000000000000000000", +// "0", +// ) + +// const expectedVariableRate = new BigNumber(daiConfiguration.baseVariableBorrowRate) +// .plus(daiConfiguration.variableRateSlope1) +// .plus(daiConfiguration.variableRateSlope2) +// .toFixed(0) + +// expect(data.currentLiquidityRate.toString()).to.be.equal( +// expectedVariableRate, +// "Invalid liquidity rate", +// ) + +// expect(data.currentVariableBorrowRate.toString()).to.be.equal( +// expectedVariableRate, +// "Invalid variable rate", +// ) + +// expect(data.currentStableBorrowRate.toString()).to.be.equal( +// new BigNumber(0.039) +// .times(RAY) +// .plus(daiConfiguration.stableRateSlope1) +// .plus(daiConfiguration.stableRateSlope2) +// .toFixed(0), +// "Invalid stable rate", +// ) +// }) +// }) diff --git a/test-suites/test-aave/scenario.spec.ts b/test-suites/test-aave/scenario.spec.ts new file mode 100644 index 00000000..55f02cad --- /dev/null +++ b/test-suites/test-aave/scenario.spec.ts @@ -0,0 +1,44 @@ +import { configuration as actionsConfiguration } from './helpers/actions'; +import { configuration as calculationsConfiguration } from './helpers/utils/calculations'; + +import fs from 'fs'; +import BigNumber from 'bignumber.js'; +import { makeSuite } from './helpers/make-suite'; +import { getReservesConfigByPool } from '../../helpers/configuration'; +import { AavePools, iAavePoolAssets, IReserveParams } from '../../helpers/types'; +import { executeStory } from './helpers/scenario-engine'; + +const scenarioFolder = './test/helpers/scenarios/'; + +const selectedScenarios: string[] = []; + +fs.readdirSync(scenarioFolder).forEach((file) => { + if (selectedScenarios.length > 0 && !selectedScenarios.includes(file)) return; + + const scenario = require(`./helpers/scenarios/${file}`); + + makeSuite(scenario.title, async (testEnv) => { + before('Initializing configuration', async () => { + // Sets BigNumber for this suite, instead of globally + BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); + + actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage + + calculationsConfiguration.reservesParams = >( + getReservesConfigByPool(AavePools.proto) + ); + }); + after('Reset', () => { + // Reset BigNumber + BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); + }); + + for (const story of scenario.stories) { + it(story.description, async function () { + // Retry the test scenarios up to 4 times if an error happens, due erratic HEVM network errors + this.retries(4); + await executeStory(story, testEnv); + }); + } + }); +}); diff --git a/test-suites/test-aave/stable-rate-economy.spec.ts b/test-suites/test-aave/stable-rate-economy.spec.ts new file mode 100644 index 00000000..1c2c156a --- /dev/null +++ b/test-suites/test-aave/stable-rate-economy.spec.ts @@ -0,0 +1,199 @@ +// import { +// LendingPoolInstance, +// LendingPoolCoreInstance, +// MintableERC20Instance, +// ATokenInstance, +// } from "../utils/typechain-types/truffle-contracts" +// import { +// iATokenBase, +// iAssetsWithoutETH, +// ITestEnvWithoutInstances, +// RateMode, +// } from "../utils/types" +// import { +// APPROVAL_AMOUNT_LENDING_POOL_CORE, +// ETHEREUM_ADDRESS, +// } from "../utils/constants" +// import { testEnvProviderWithoutInstances} from "../utils/truffle/dlp-tests-env" +// import {convertToCurrencyDecimals} from "../utils/misc-utils" + +// const expectRevert = require("@openzeppelin/test-helpers").expectRevert + +// contract("LendingPool - stable rate economy tests", async ([deployer, ...users]) => { +// let _testEnvProvider: ITestEnvWithoutInstances +// let _lendingPoolInstance: LendingPoolInstance +// let _lendingPoolCoreInstance: LendingPoolCoreInstance +// let _aTokenInstances: iATokenBase +// let _tokenInstances: iAssetsWithoutETH + +// let _daiAddress: string + +// let _depositorAddress: string +// let _borrowerAddress: string + +// let _web3: Web3 + +// before("Initializing LendingPool test variables", async () => { +// console.time('setup-test'); +// _testEnvProvider = await testEnvProviderWithoutInstances( +// artifacts, +// [deployer, ...users] +// ) + +// const { +// getWeb3, +// getAllAssetsInstances, +// getFirstBorrowerAddressOnTests, +// getFirstDepositorAddressOnTests, +// getLendingPoolInstance, +// getLendingPoolCoreInstance, +// getATokenInstances +// } = _testEnvProvider + +// const instances = await Promise.all([ +// getLendingPoolInstance(), +// getLendingPoolCoreInstance(), +// getATokenInstances(), +// getAllAssetsInstances() +// ]) +// _lendingPoolInstance = instances[0] +// _lendingPoolCoreInstance = instances[1] +// _aTokenInstances = instances[2] +// _tokenInstances = instances[3] +// _daiAddress = _tokenInstances.DAI.address +// _depositorAddress = await getFirstDepositorAddressOnTests() +// _borrowerAddress = await getFirstBorrowerAddressOnTests() + +// _web3 = await getWeb3() +// console.timeEnd('setup-test'); +// }) + +// it("BORROW - Test user cannot borrow using the same currency as collateral", async () => { +// const {aDAI: aDaiInstance} = _aTokenInstances +// const {DAI: daiInstance} = _tokenInstances + +// //mints DAI to depositor +// await daiInstance.mint(await convertToCurrencyDecimals(daiInstance.address, "1000"), { +// from: _depositorAddress, +// }) + +// //mints DAI to borrower +// await daiInstance.mint(await convertToCurrencyDecimals(daiInstance.address, "1000"), { +// from: _borrowerAddress, +// }) + +// //approve protocol to access depositor wallet +// await daiInstance.approve(_lendingPoolCoreInstance.address, APPROVAL_AMOUNT_LENDING_POOL_CORE, { +// from: _depositorAddress, +// }) + +// //approve protocol to access borrower wallet +// await daiInstance.approve(_lendingPoolCoreInstance.address, APPROVAL_AMOUNT_LENDING_POOL_CORE, { +// from: _borrowerAddress, +// }) + +// const amountDAItoDeposit = await convertToCurrencyDecimals(_daiAddress, "1000") + +// //user 1 deposits 1000 DAI +// const txResult = await _lendingPoolInstance.deposit(_daiAddress, amountDAItoDeposit, "0", { +// from: _depositorAddress, +// }) + +// //user 2 deposits 1000 DAI, tries to borrow. Needs to be reverted as you can't borrow at a stable rate with the same collateral as the currency. +// const amountDAIToDepositBorrower = await convertToCurrencyDecimals(_daiAddress, "1000") +// await _lendingPoolInstance.deposit(_daiAddress, amountDAIToDepositBorrower, "0", { +// from: _borrowerAddress, +// }) + +// const data: any = await _lendingPoolInstance.getReserveData(_daiAddress) + +// //user 2 tries to borrow +// const amountDAIToBorrow = await convertToCurrencyDecimals(_daiAddress, "250") + +// //user 2 tries to borrow +// await expectRevert( +// _lendingPoolInstance.borrow(_daiAddress, amountDAIToBorrow, RateMode.Stable, "0", { +// from: _borrowerAddress, +// }), +// "User cannot borrow the selected amount with a stable rate", +// ) +// }) + +// it("BORROW - Test user cannot borrow more than 25% of the liquidity available", async () => { +// const {aDAI: aDaiInstance} = _aTokenInstances +// const {DAI: daiInstance} = _tokenInstances + +// //redeem the DAI previously deposited +// const amountADAIToRedeem = await convertToCurrencyDecimals(aDaiInstance.address, "1000") +// await aDaiInstance.redeem(amountADAIToRedeem, { +// from: _borrowerAddress, +// }) + +// //user 2 deposits 5 ETH tries to borrow. needs to be reverted as you can't borrow more than 25% of the available reserve (250 DAI) +// const amountETHToDeposit = await convertToCurrencyDecimals(ETHEREUM_ADDRESS, "5") +// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, amountETHToDeposit, "0", { +// from: _borrowerAddress, +// value: amountETHToDeposit, +// }) + +// const data: any = await _lendingPoolInstance.getReserveData(_daiAddress) + +// const amountDAIToBorrow = await convertToCurrencyDecimals(_daiAddress, "500") + +// //user 2 tries to borrow +// await expectRevert( +// _lendingPoolInstance.borrow(_daiAddress, amountDAIToBorrow, RateMode.Stable, "0", { +// from: _borrowerAddress, +// }), +// "User is trying to borrow too much liquidity at a stable rate", +// ) +// }) + +// it("BORROW - Test user can still borrow a currency that he previously deposited as a collateral but he transferred/redeemed", async () => { +// const {aDAI: aDaiInstance} = _aTokenInstances +// const {DAI: daiInstance} = _tokenInstances + +// const user = users[2] + +// //user deposits 1000 DAI +// await daiInstance.mint(await convertToCurrencyDecimals(daiInstance.address, "1000"), { +// from: user, +// }) +// await daiInstance.approve(_lendingPoolCoreInstance.address, APPROVAL_AMOUNT_LENDING_POOL_CORE, { +// from: user, +// }) + +// const amountDAIToDeposit = await convertToCurrencyDecimals(daiInstance.address, "1000") +// await _lendingPoolInstance.deposit(daiInstance.address, amountDAIToDeposit, "0", { +// from: user, +// }) + +// //user deposits 5 ETH as collateral +// const amountETHToDeposit = await convertToCurrencyDecimals(ETHEREUM_ADDRESS, "5") +// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, amountETHToDeposit, "0", { +// from: user, +// value: amountETHToDeposit, +// }) + +// //user transfers to another address all the overlying aDAI + +// const aDAIBalance = await aDaiInstance.balanceOf(user) + +// await aDaiInstance.transfer(users[3], aDAIBalance, { +// from: user, +// }) + +// //check the underlying balance is 0 +// const userData: any = await _lendingPoolInstance.getUserReserveData(daiInstance.address, user) + +// expect(userData.currentATokenBalance.toString()).to.be.equal("0") + +// //user tries to borrow the DAI at a stable rate using the ETH as collateral +// const amountDAIToBorrow = await convertToCurrencyDecimals(_daiAddress, "100") + +// //user tries to borrow. No revert expected +// await _lendingPoolInstance.borrow(_daiAddress, amountDAIToBorrow, RateMode.Stable, "0", { +// from: user, +// }) +// }) +// }) diff --git a/test-suites/test-aave/stable-token.spec.ts b/test-suites/test-aave/stable-token.spec.ts new file mode 100644 index 00000000..1e3ad27b --- /dev/null +++ b/test-suites/test-aave/stable-token.spec.ts @@ -0,0 +1,37 @@ +import { expect } from 'chai'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors } from '../../helpers/types'; +import { getStableDebtToken } from '../../helpers/contracts-getters'; + +makeSuite('Stable debt token tests', (testEnv: TestEnv) => { + const { CT_CALLER_MUST_BE_LENDING_POOL } = ProtocolErrors; + + it('Tries to invoke mint not being the LendingPool', async () => { + const { deployer, pool, dai, helpersContract } = testEnv; + + const daiStableDebtTokenAddress = (await helpersContract.getReserveTokensAddresses(dai.address)) + .stableDebtTokenAddress; + + const stableDebtContract = await getStableDebtToken(daiStableDebtTokenAddress); + + await expect( + stableDebtContract.mint(deployer.address, deployer.address, '1', '1') + ).to.be.revertedWith(CT_CALLER_MUST_BE_LENDING_POOL); + }); + + it('Tries to invoke burn not being the LendingPool', async () => { + const { deployer, dai, helpersContract } = testEnv; + + const daiStableDebtTokenAddress = (await helpersContract.getReserveTokensAddresses(dai.address)) + .stableDebtTokenAddress; + + const stableDebtContract = await getStableDebtToken(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( + CT_CALLER_MUST_BE_LENDING_POOL + ); + }); +}); diff --git a/test-suites/test-aave/subgraph-scenarios.spec.ts b/test-suites/test-aave/subgraph-scenarios.spec.ts new file mode 100644 index 00000000..24959a41 --- /dev/null +++ b/test-suites/test-aave/subgraph-scenarios.spec.ts @@ -0,0 +1,32 @@ +import { configuration as actionsConfiguration } from './helpers/actions'; +import { configuration as calculationsConfiguration } from './helpers/utils/calculations'; + +import BigNumber from 'bignumber.js'; +import { makeSuite } from './helpers/make-suite'; +import { getReservesConfigByPool } from '../../helpers/configuration'; +import { AavePools, iAavePoolAssets, IReserveParams } from '../../helpers/types'; +import { executeStory } from './helpers/scenario-engine'; + +makeSuite('Subgraph scenario tests', async (testEnv) => { + let story: any; + let scenario; + before('Initializing configuration', async () => { + const scenario = require(`./helpers/scenarios/borrow-repay-stable`); + story = scenario.stories[0]; + // Sets BigNumber for this suite, instead of globally + BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); + + actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage + + calculationsConfiguration.reservesParams = >( + getReservesConfigByPool(AavePools.proto) + ); + }); + after('Reset', () => { + // Reset BigNumber + BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); + }); + it('deposit-borrow', async () => { + await executeStory(story, testEnv); + }); +}); diff --git a/test-suites/test-aave/uniswapAdapters.base.spec.ts b/test-suites/test-aave/uniswapAdapters.base.spec.ts new file mode 100644 index 00000000..1fe88370 --- /dev/null +++ b/test-suites/test-aave/uniswapAdapters.base.spec.ts @@ -0,0 +1,227 @@ +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { getMockUniswapRouter } from '../../helpers/contracts-getters'; +import { MockUniswapV2Router02 } from '../../types/MockUniswapV2Router02'; +import BigNumber from 'bignumber.js'; +import { evmRevert, evmSnapshot } from '../../helpers/misc-utils'; +import { ethers } from 'ethers'; +import { USD_ADDRESS } from '../../helpers/constants'; +const { parseEther } = ethers.utils; + +const { expect } = require('chai'); + +makeSuite('Uniswap adapters', (testEnv: TestEnv) => { + let mockUniswapRouter: MockUniswapV2Router02; + let evmSnapshotId: string; + + before(async () => { + mockUniswapRouter = await getMockUniswapRouter(); + }); + + beforeEach(async () => { + evmSnapshotId = await evmSnapshot(); + }); + + afterEach(async () => { + await evmRevert(evmSnapshotId); + }); + + describe('BaseUniswapAdapter', () => { + describe('getAmountsOut', () => { + it('should return the estimated amountOut and prices for the asset swap', async () => { + const { weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv; + + const amountIn = parseEther('1'); + const flashloanPremium = amountIn.mul(9).div(10000); + const amountToSwap = amountIn.sub(flashloanPremium); + + const wethPrice = await oracle.getAssetPrice(weth.address); + const daiPrice = await oracle.getAssetPrice(dai.address); + const usdPrice = await oracle.getAssetPrice(USD_ADDRESS); + + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountToSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const outPerInPrice = amountToSwap + .mul(parseEther('1')) + .mul(parseEther('1')) + .div(expectedDaiAmount.mul(parseEther('1'))); + const ethUsdValue = amountIn + .mul(wethPrice) + .div(parseEther('1')) + .mul(usdPrice) + .div(parseEther('1')); + const daiUsdValue = expectedDaiAmount + .mul(daiPrice) + .div(parseEther('1')) + .mul(usdPrice) + .div(parseEther('1')); + + await mockUniswapRouter.setAmountOut( + amountToSwap, + weth.address, + dai.address, + expectedDaiAmount + ); + + const result = await uniswapLiquiditySwapAdapter.getAmountsOut( + amountIn, + weth.address, + dai.address + ); + + expect(result['0']).to.be.eq(expectedDaiAmount); + expect(result['1']).to.be.eq(outPerInPrice); + expect(result['2']).to.be.eq(ethUsdValue); + expect(result['3']).to.be.eq(daiUsdValue); + }); + it('should work correctly with different decimals', async () => { + const { aave, usdc, uniswapLiquiditySwapAdapter, oracle } = testEnv; + + const amountIn = parseEther('10'); + const flashloanPremium = amountIn.mul(9).div(10000); + const amountToSwap = amountIn.sub(flashloanPremium); + + const aavePrice = await oracle.getAssetPrice(aave.address); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + const usdPrice = await oracle.getAssetPrice(USD_ADDRESS); + + const expectedUSDCAmount = await convertToCurrencyDecimals( + usdc.address, + new BigNumber(amountToSwap.toString()).div(usdcPrice.toString()).toFixed(0) + ); + + const outPerInPrice = amountToSwap + .mul(parseEther('1')) + .mul('1000000') // usdc 6 decimals + .div(expectedUSDCAmount.mul(parseEther('1'))); + + const aaveUsdValue = amountIn + .mul(aavePrice) + .div(parseEther('1')) + .mul(usdPrice) + .div(parseEther('1')); + + const usdcUsdValue = expectedUSDCAmount + .mul(usdcPrice) + .div('1000000') // usdc 6 decimals + .mul(usdPrice) + .div(parseEther('1')); + + await mockUniswapRouter.setAmountOut( + amountToSwap, + aave.address, + usdc.address, + expectedUSDCAmount + ); + + const result = await uniswapLiquiditySwapAdapter.getAmountsOut( + amountIn, + aave.address, + usdc.address + ); + + expect(result['0']).to.be.eq(expectedUSDCAmount); + expect(result['1']).to.be.eq(outPerInPrice); + expect(result['2']).to.be.eq(aaveUsdValue); + expect(result['3']).to.be.eq(usdcUsdValue); + }); + }); + + describe('getAmountsIn', () => { + it('should return the estimated required amountIn for the asset swap', async () => { + const { weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv; + + const amountIn = parseEther('1'); + const flashloanPremium = amountIn.mul(9).div(10000); + const amountToSwap = amountIn.add(flashloanPremium); + + const wethPrice = await oracle.getAssetPrice(weth.address); + const daiPrice = await oracle.getAssetPrice(dai.address); + const usdPrice = await oracle.getAssetPrice(USD_ADDRESS); + + const amountOut = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountIn.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const inPerOutPrice = amountOut + .mul(parseEther('1')) + .mul(parseEther('1')) + .div(amountToSwap.mul(parseEther('1'))); + + const ethUsdValue = amountToSwap + .mul(wethPrice) + .div(parseEther('1')) + .mul(usdPrice) + .div(parseEther('1')); + const daiUsdValue = amountOut + .mul(daiPrice) + .div(parseEther('1')) + .mul(usdPrice) + .div(parseEther('1')); + + await mockUniswapRouter.setAmountIn(amountOut, weth.address, dai.address, amountIn); + + const result = await uniswapLiquiditySwapAdapter.getAmountsIn( + amountOut, + weth.address, + dai.address + ); + + expect(result['0']).to.be.eq(amountToSwap); + expect(result['1']).to.be.eq(inPerOutPrice); + expect(result['2']).to.be.eq(ethUsdValue); + expect(result['3']).to.be.eq(daiUsdValue); + }); + it('should work correctly with different decimals', async () => { + const { aave, usdc, uniswapLiquiditySwapAdapter, oracle } = testEnv; + + const amountIn = parseEther('10'); + const flashloanPremium = amountIn.mul(9).div(10000); + const amountToSwap = amountIn.add(flashloanPremium); + + const aavePrice = await oracle.getAssetPrice(aave.address); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + const usdPrice = await oracle.getAssetPrice(USD_ADDRESS); + + const amountOut = await convertToCurrencyDecimals( + usdc.address, + new BigNumber(amountToSwap.toString()).div(usdcPrice.toString()).toFixed(0) + ); + + const inPerOutPrice = amountOut + .mul(parseEther('1')) + .mul(parseEther('1')) + .div(amountToSwap.mul('1000000')); // usdc 6 decimals + + const aaveUsdValue = amountToSwap + .mul(aavePrice) + .div(parseEther('1')) + .mul(usdPrice) + .div(parseEther('1')); + + const usdcUsdValue = amountOut + .mul(usdcPrice) + .div('1000000') // usdc 6 decimals + .mul(usdPrice) + .div(parseEther('1')); + + await mockUniswapRouter.setAmountIn(amountOut, aave.address, usdc.address, amountIn); + + const result = await uniswapLiquiditySwapAdapter.getAmountsIn( + amountOut, + aave.address, + usdc.address + ); + + expect(result['0']).to.be.eq(amountToSwap); + expect(result['1']).to.be.eq(inPerOutPrice); + expect(result['2']).to.be.eq(aaveUsdValue); + expect(result['3']).to.be.eq(usdcUsdValue); + }); + }); + }); +}); diff --git a/test-suites/test-aave/uniswapAdapters.flashLiquidation.spec.ts b/test-suites/test-aave/uniswapAdapters.flashLiquidation.spec.ts new file mode 100644 index 00000000..cc161b4b --- /dev/null +++ b/test-suites/test-aave/uniswapAdapters.flashLiquidation.spec.ts @@ -0,0 +1,850 @@ +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { + convertToCurrencyDecimals, + buildFlashLiquidationAdapterParams, +} from '../../helpers/contracts-helpers'; +import { getMockUniswapRouter } from '../../helpers/contracts-getters'; +import { deployFlashLiquidationAdapter } from '../../helpers/contracts-deployments'; +import { MockUniswapV2Router02 } from '../../types/MockUniswapV2Router02'; +import BigNumber from 'bignumber.js'; +import { DRE, evmRevert, evmSnapshot, increaseTime, waitForTx } from '../../helpers/misc-utils'; +import { ethers } from 'ethers'; +import { ProtocolErrors, RateMode } from '../../helpers/types'; +import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, oneEther } from '../../helpers/constants'; +import { getUserData } from './helpers/utils/helpers'; +import { calcExpectedStableDebtTokenBalance } from './helpers/utils/calculations'; +const { expect } = require('chai'); + +makeSuite('Uniswap adapters', (testEnv: TestEnv) => { + let mockUniswapRouter: MockUniswapV2Router02; + let evmSnapshotId: string; + const { INVALID_HF, LP_LIQUIDATION_CALL_FAILED } = ProtocolErrors; + + before(async () => { + mockUniswapRouter = await getMockUniswapRouter(); + }); + + const depositAndHFBelowOne = async () => { + const { dai, weth, users, pool, oracle } = testEnv; + const depositor = users[0]; + const borrower = users[1]; + + //mints DAI to depositor + await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access depositor wallet + await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 1 deposits 1000 DAI + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); + //user 2 deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); + + //approve protocol to access the borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 2 borrows + + const userGlobalDataBefore = await pool.getUserAccountData(borrower.address); + const daiPrice = await oracle.getAssetPrice(dai.address); + + const amountDAIToBorrow = await convertToCurrencyDecimals( + dai.address, + new BigNumber(userGlobalDataBefore.availableBorrowsETH.toString()) + .div(daiPrice.toString()) + .multipliedBy(0.95) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.equal( + '8250', + INVALID_HF + ); + + await oracle.setAssetPrice( + dai.address, + new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0) + ); + + const userGlobalData = await pool.getUserAccountData(borrower.address); + + expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( + oneEther.toFixed(0), + INVALID_HF + ); + }; + + const depositSameAssetAndHFBelowOne = async () => { + const { dai, weth, users, pool, oracle } = testEnv; + const depositor = users[0]; + const borrower = users[1]; + + //mints DAI to depositor + await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access depositor wallet + await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 1 deposits 1000 DAI + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); + //user 2 deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); + + //approve protocol to access the borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 2 borrows + + const userGlobalDataBefore = await pool.getUserAccountData(borrower.address); + const daiPrice = await oracle.getAssetPrice(dai.address); + + const amountDAIToBorrow = await convertToCurrencyDecimals( + dai.address, + new BigNumber(userGlobalDataBefore.availableBorrowsETH.toString()) + .div(daiPrice.toString()) + .multipliedBy(0.8) + .toFixed(0) + ); + await waitForTx( + await pool + .connect(borrower.signer) + .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address) + ); + + const userGlobalDataBefore2 = await pool.getUserAccountData(borrower.address); + + const amountWETHToBorrow = new BigNumber(userGlobalDataBefore2.availableBorrowsETH.toString()) + .multipliedBy(0.8) + .toFixed(0); + + await pool + .connect(borrower.signer) + .borrow(weth.address, amountWETHToBorrow, RateMode.Variable, '0', borrower.address); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.equal( + '8250', + INVALID_HF + ); + + await oracle.setAssetPrice( + dai.address, + new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0) + ); + + const userGlobalData = await pool.getUserAccountData(borrower.address); + + expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( + oneEther.toFixed(0), + INVALID_HF + ); + }; + + beforeEach(async () => { + evmSnapshotId = await evmSnapshot(); + }); + + afterEach(async () => { + await evmRevert(evmSnapshotId); + }); + + describe('Flash Liquidation Adapter', () => { + before('Before LendingPool liquidation: set config', () => { + BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); + }); + + after('After LendingPool liquidation: reset config', () => { + BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); + }); + + describe('constructor', () => { + it('should deploy with correct parameters', async () => { + const { addressesProvider, weth } = testEnv; + await deployFlashLiquidationAdapter([ + addressesProvider.address, + mockUniswapRouter.address, + weth.address, + ]); + }); + + it('should revert if not valid addresses provider', async () => { + const { weth } = testEnv; + expect( + deployFlashLiquidationAdapter([ + mockUniswapRouter.address, + mockUniswapRouter.address, + weth.address, + ]) + ).to.be.reverted; + }); + }); + + describe('executeOperation: succesfully liquidateCall and swap via Flash Loan with profits', () => { + it('Liquidates the borrow with profit', async () => { + await depositAndHFBelowOne(); + await increaseTime(100); + + const { + dai, + weth, + users, + pool, + oracle, + helpersContract, + flashLiquidationAdapter, + } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + const expectedSwap = ethers.utils.parseEther('0.4'); + + const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); + + // Set how much ETH will be sold and swapped for DAI at Uniswap mock + await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); + + const collateralPrice = await oracle.getAssetPrice(weth.address); + const principalPrice = await oracle.getAssetPrice(dai.address); + const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(dai.address) + ).decimals.toString(); + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + + const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div( + new BigNumber(collateralPrice.toString()).times( + new BigNumber(10).pow(principalDecimals) + ) + ) + .div(100) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) + .multipliedBy(1.0009) + .toFixed(0); + + const expectedProfit = ethers.BigNumber.from(expectedCollateralLiquidated.toString()).sub( + expectedSwap + ); + + const params = buildFlashLiquidationAdapterParams( + weth.address, + dai.address, + borrower.address, + amountToLiquidate, + false + ); + const tx = await pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [dai.address], + [amountToLiquidate], + [0], + borrower.address, + params, + 0 + ); + + // Expect Swapped event + await expect(Promise.resolve(tx)).to.emit(flashLiquidationAdapter, 'Swapped'); + + // Expect LiquidationCall event + await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); + + const userReserveDataAfter = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + const liquidatorWethBalanceAfter = await weth.balanceOf(liquidator.address); + + const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); + const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + + if (!tx.blockNumber) { + expect(false, 'Invalid block number'); + return; + } + const txTimestamp = new BigNumber( + (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp + ); + + const stableDebtBeforeTx = calcExpectedStableDebtTokenBalance( + userReserveDataBefore.principalStableDebt, + userReserveDataBefore.stableBorrowRate, + userReserveDataBefore.stableRateLastUpdated, + txTimestamp + ); + + const collateralAssetContractBalance = await weth.balanceOf( + flashLiquidationAdapter.address + ); + const borrowAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); + + expect(collateralAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); + expect(borrowAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); + + expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( + stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), + 'Invalid user debt after liquidation' + ); + + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( + daiReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + daiReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + + expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(daiReserveDataBefore.availableLiquidity.toString()) + .plus(flashLoanDebt) + .toFixed(0), + 'Invalid principal available liquidity' + ); + + expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) + .minus(expectedCollateralLiquidated) + .toFixed(0), + 'Invalid collateral available liquidity' + ); + + // Profit after flash loan liquidation + expect(liquidatorWethBalanceAfter).to.be.equal( + liquidatorWethBalanceBefore.add(expectedProfit), + 'Invalid expected WETH profit' + ); + }); + }); + + describe('executeOperation: succesfully liquidateCall with same asset via Flash Loan, but no swap needed', () => { + it('Liquidates the borrow with profit', async () => { + await depositSameAssetAndHFBelowOne(); + await increaseTime(100); + + const { weth, users, pool, oracle, helpersContract, flashLiquidationAdapter } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + + const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); + + const assetPrice = await oracle.getAssetPrice(weth.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + weth.address, + borrower.address + ); + + const assetDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const amountToLiquidate = userReserveDataBefore.currentVariableDebt.div(2).toFixed(0); + + const expectedCollateralLiquidated = new BigNumber(assetPrice.toString()) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(assetDecimals)) + .div(new BigNumber(assetPrice.toString()).times(new BigNumber(10).pow(assetDecimals))) + .div(100) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) + .multipliedBy(1.0009) + .toFixed(0); + + const params = buildFlashLiquidationAdapterParams( + weth.address, + weth.address, + borrower.address, + amountToLiquidate, + false + ); + const tx = await pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [weth.address], + [amountToLiquidate], + [0], + borrower.address, + params, + 0 + ); + + // Dont expect Swapped event due is same asset + await expect(Promise.resolve(tx)).to.not.emit(flashLiquidationAdapter, 'Swapped'); + + // Expect LiquidationCall event + await expect(Promise.resolve(tx)) + .to.emit(pool, 'LiquidationCall') + .withArgs( + weth.address, + weth.address, + borrower.address, + amountToLiquidate.toString(), + expectedCollateralLiquidated.toString(), + flashLiquidationAdapter.address, + false + ); + + const borrowAssetContractBalance = await weth.balanceOf(flashLiquidationAdapter.address); + + expect(borrowAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); + }); + }); + + describe('executeOperation: succesfully liquidateCall and swap via Flash Loan without profits', () => { + it('Liquidates the borrow', async () => { + await depositAndHFBelowOne(); + await increaseTime(100); + + const { + dai, + weth, + users, + pool, + oracle, + helpersContract, + flashLiquidationAdapter, + } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); + + const collateralPrice = await oracle.getAssetPrice(weth.address); + const principalPrice = await oracle.getAssetPrice(dai.address); + const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(dai.address) + ).decimals.toString(); + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + + const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div( + new BigNumber(collateralPrice.toString()).times( + new BigNumber(10).pow(principalDecimals) + ) + ) + .div(100) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) + .multipliedBy(1.0009) + .toFixed(0); + + // Set how much ETH will be sold and swapped for DAI at Uniswap mock + await ( + await mockUniswapRouter.setAmountToSwap( + weth.address, + expectedCollateralLiquidated.toString() + ) + ).wait(); + + const params = buildFlashLiquidationAdapterParams( + weth.address, + dai.address, + borrower.address, + amountToLiquidate, + false + ); + const tx = await pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [dai.address], + [flashLoanDebt], + [0], + borrower.address, + params, + 0 + ); + + // Expect Swapped event + await expect(Promise.resolve(tx)).to.emit(flashLiquidationAdapter, 'Swapped'); + + // Expect LiquidationCall event + await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); + + const userReserveDataAfter = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + const liquidatorWethBalanceAfter = await weth.balanceOf(liquidator.address); + + const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); + const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + + if (!tx.blockNumber) { + expect(false, 'Invalid block number'); + return; + } + const txTimestamp = new BigNumber( + (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp + ); + + const stableDebtBeforeTx = calcExpectedStableDebtTokenBalance( + userReserveDataBefore.principalStableDebt, + userReserveDataBefore.stableBorrowRate, + userReserveDataBefore.stableRateLastUpdated, + txTimestamp + ); + + const collateralAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); + const borrowAssetContractBalance = await weth.balanceOf(flashLiquidationAdapter.address); + + expect(collateralAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); + expect(borrowAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); + expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( + stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), + 'Invalid user debt after liquidation' + ); + + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( + daiReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + daiReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + + expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) + .minus(expectedCollateralLiquidated) + .toFixed(0), + 'Invalid collateral available liquidity' + ); + + // Net Profit == 0 after flash loan liquidation + expect(liquidatorWethBalanceAfter).to.be.equal( + liquidatorWethBalanceBefore, + 'Invalid expected WETH profit' + ); + }); + }); + + describe('executeOperation: succesfully liquidateCall all available debt and swap via Flash Loan ', () => { + it('Liquidates the borrow', async () => { + await depositAndHFBelowOne(); + await increaseTime(100); + + const { + dai, + weth, + users, + pool, + oracle, + helpersContract, + flashLiquidationAdapter, + } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); + + const collateralPrice = await oracle.getAssetPrice(weth.address); + const principalPrice = await oracle.getAssetPrice(dai.address); + const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(dai.address) + ).decimals.toString(); + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + const extraAmount = new BigNumber(amountToLiquidate).times('1.15').toFixed(0); + + const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div( + new BigNumber(collateralPrice.toString()).times( + new BigNumber(10).pow(principalDecimals) + ) + ) + .div(100) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) + .multipliedBy(1.0009) + .toFixed(0); + + // Set how much ETH will be sold and swapped for DAI at Uniswap mock + await ( + await mockUniswapRouter.setAmountToSwap( + weth.address, + expectedCollateralLiquidated.toString() + ) + ).wait(); + + const params = buildFlashLiquidationAdapterParams( + weth.address, + dai.address, + borrower.address, + MAX_UINT_AMOUNT, + false + ); + const tx = await pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [dai.address], + [extraAmount], + [0], + borrower.address, + params, + 0 + ); + + // Expect Swapped event + await expect(Promise.resolve(tx)).to.emit(flashLiquidationAdapter, 'Swapped'); + + // Expect LiquidationCall event + await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); + + const collateralAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); + const borrowAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); + + expect(collateralAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); + expect(borrowAssetContractBalance).to.be.equal( + '0', + 'Contract address should not keep any balance.' + ); + }); + }); + + describe('executeOperation: invalid params', async () => { + it('Revert if debt asset is different than requested flash loan token', async () => { + await depositAndHFBelowOne(); + + const { dai, weth, users, pool, helpersContract, flashLiquidationAdapter } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + const expectedSwap = ethers.utils.parseEther('0.4'); + + // Set how much ETH will be sold and swapped for DAI at Uniswap mock + await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); + + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + + // Wrong debt asset + const params = buildFlashLiquidationAdapterParams( + weth.address, + weth.address, // intentionally bad + borrower.address, + amountToLiquidate, + false + ); + await expect( + pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [dai.address], + [amountToLiquidate], + [0], + borrower.address, + params, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + }); + + it('Revert if debt asset amount to liquidate is greater than requested flash loan', async () => { + await depositAndHFBelowOne(); + + const { dai, weth, users, pool, helpersContract, flashLiquidationAdapter } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + const expectedSwap = ethers.utils.parseEther('0.4'); + + // Set how much ETH will be sold and swapped for DAI at Uniswap mock + await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); + + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2); + + // Correct params + const params = buildFlashLiquidationAdapterParams( + weth.address, + dai.address, + borrower.address, + amountToLiquidate.toString(), + false + ); + // Bad flash loan params: requested DAI amount below amountToLiquidate + await expect( + pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [dai.address], + [amountToLiquidate.div(2).toString()], + [0], + borrower.address, + params, + 0 + ) + ).to.be.revertedWith(LP_LIQUIDATION_CALL_FAILED); + }); + + it('Revert if requested multiple assets', async () => { + await depositAndHFBelowOne(); + + const { dai, weth, users, pool, helpersContract, flashLiquidationAdapter } = testEnv; + + const liquidator = users[3]; + const borrower = users[1]; + const expectedSwap = ethers.utils.parseEther('0.4'); + + // Set how much ETH will be sold and swapped for DAI at Uniswap mock + await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); + + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2); + + // Correct params + const params = buildFlashLiquidationAdapterParams( + weth.address, + dai.address, + borrower.address, + amountToLiquidate.toString(), + false + ); + // Bad flash loan params: requested multiple assets + await expect( + pool + .connect(liquidator.signer) + .flashLoan( + flashLiquidationAdapter.address, + [dai.address, weth.address], + [10, 10], + [0], + borrower.address, + params, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + }); + }); + }); +}); diff --git a/test-suites/test-aave/uniswapAdapters.liquiditySwap.spec.ts b/test-suites/test-aave/uniswapAdapters.liquiditySwap.spec.ts new file mode 100644 index 00000000..42224c52 --- /dev/null +++ b/test-suites/test-aave/uniswapAdapters.liquiditySwap.spec.ts @@ -0,0 +1,1854 @@ +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { + convertToCurrencyDecimals, + getContract, + buildPermitParams, + getSignatureFromTypedData, + buildLiquiditySwapParams, +} from '../../helpers/contracts-helpers'; +import { getMockUniswapRouter } from '../../helpers/contracts-getters'; +import { deployUniswapLiquiditySwapAdapter } from '../../helpers/contracts-deployments'; +import { MockUniswapV2Router02 } from '../../types/MockUniswapV2Router02'; +import { Zero } from '@ethersproject/constants'; +import BigNumber from 'bignumber.js'; +import { DRE, evmRevert, evmSnapshot } from '../../helpers/misc-utils'; +import { ethers } from 'ethers'; +import { eContractid } from '../../helpers/types'; +import { AToken } from '../../types/AToken'; +import { BUIDLEREVM_CHAINID } from '../../helpers/buidler-constants'; +import { MAX_UINT_AMOUNT } from '../../helpers/constants'; +const { parseEther } = ethers.utils; + +const { expect } = require('chai'); + +makeSuite('Uniswap adapters', (testEnv: TestEnv) => { + let mockUniswapRouter: MockUniswapV2Router02; + let evmSnapshotId: string; + + before(async () => { + mockUniswapRouter = await getMockUniswapRouter(); + }); + + beforeEach(async () => { + evmSnapshotId = await evmSnapshot(); + }); + + afterEach(async () => { + await evmRevert(evmSnapshotId); + }); + + describe('UniswapLiquiditySwapAdapter', () => { + describe('constructor', () => { + it('should deploy with correct parameters', async () => { + const { addressesProvider, weth } = testEnv; + await deployUniswapLiquiditySwapAdapter([ + addressesProvider.address, + mockUniswapRouter.address, + weth.address, + ]); + }); + + it('should revert if not valid addresses provider', async () => { + const { weth } = testEnv; + expect( + deployUniswapLiquiditySwapAdapter([ + mockUniswapRouter.address, + mockUniswapRouter.address, + weth.address, + ]) + ).to.be.reverted; + }); + }); + + describe('executeOperation', () => { + beforeEach(async () => { + const { users, weth, dai, usdc, pool, deployer } = testEnv; + const userAddress = users[0].address; + + // Provide liquidity + await dai.mint(parseEther('20000')); + await dai.approve(pool.address, parseEther('20000')); + await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); + + const usdcAmount = await convertToCurrencyDecimals(usdc.address, '10'); + await usdc.mint(usdcAmount); + await usdc.approve(pool.address, usdcAmount); + await pool.deposit(usdc.address, usdcAmount, deployer.address, 0); + + // Make a deposit for user + await weth.mint(parseEther('100')); + await weth.approve(pool.address, parseEther('100')); + await pool.deposit(weth.address, parseEther('100'), userAddress, 0); + }); + + it('should correctly swap tokens and deposit the out tokens in the pool', async () => { + const { + users, + weth, + oracle, + dai, + aDai, + aWETH, + pool, + uniswapLiquiditySwapAdapter, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + + // User will swap liquidity 10 aEth to aDai + const liquidityToSwap = parseEther('10'); + await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + // Subtract the FL fee from the amount to be swapped 0,09% + const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); + + const params = buildLiquiditySwapParams( + [dai.address], + [expectedDaiAmount], + [0], + [0], + [0], + [0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params, + 0 + ) + ) + .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') + .withArgs(weth.address, dai.address, flashloanAmount.toString(), expectedDaiAmount); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmount); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); + }); + + it('should correctly swap and deposit multiple tokens', async () => { + const { + users, + weth, + oracle, + dai, + aDai, + aWETH, + usdc, + pool, + uniswapLiquiditySwapAdapter, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmountForEth = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const collateralDecimals = (await usdc.decimals()).toString(); + const principalDecimals = (await dai.decimals()).toString(); + + const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div( + new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .toFixed(0) + ); + + // Make a deposit for user + await usdc.connect(user).mint(amountUSDCtoSwap); + await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); + await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + + const aUsdcData = await pool.getReserveData(usdc.address); + const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); + await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); + + await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountWETHtoSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + await aUsdc.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountUSDCtoSwap); + const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); + + // Subtract the FL fee from the amount to be swapped 0,09% + const wethFlashloanAmount = new BigNumber(amountWETHtoSwap.toString()) + .div(1.0009) + .toFixed(0); + const usdcFlashloanAmount = new BigNumber(amountUSDCtoSwap.toString()) + .div(1.0009) + .toFixed(0); + + const params = buildLiquiditySwapParams( + [dai.address, dai.address], + [expectedDaiAmountForEth, expectedDaiAmountForUsdc], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [ + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + ], + [ + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + ], + [false, false] + ); + + await pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address, usdc.address], + [wethFlashloanAmount.toString(), usdcFlashloanAmount.toString()], + [0, 0], + userAddress, + params, + 0 + ); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const userAUsdcBalance = await aUsdc.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); + expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); + expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); + }); + + it('should correctly swap and deposit multiple tokens using permit', async () => { + const { + users, + weth, + oracle, + dai, + aDai, + aWETH, + usdc, + pool, + uniswapLiquiditySwapAdapter, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + + const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmountForEth = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const collateralDecimals = (await usdc.decimals()).toString(); + const principalDecimals = (await dai.decimals()).toString(); + + const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div( + new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .toFixed(0) + ); + + // Make a deposit for user + await usdc.connect(user).mint(amountUSDCtoSwap); + await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); + await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + + const aUsdcData = await pool.getReserveData(usdc.address); + const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); + await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); + + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); + + const wethFlashloanAmount = new BigNumber(amountWETHtoSwap.toString()) + .div(1.0009) + .toFixed(0); + + const usdcFlashloanAmount = new BigNumber(amountUSDCtoSwap.toString()) + .div(1.0009) + .toFixed(0); + + const aWethNonce = (await aWETH._nonces(userAddress)).toNumber(); + const aWethMsgParams = buildPermitParams( + chainId, + aWETH.address, + '1', + await aWETH.name(), + userAddress, + uniswapLiquiditySwapAdapter.address, + aWethNonce, + deadline, + amountWETHtoSwap.toString() + ); + const { v: aWETHv, r: aWETHr, s: aWETHs } = getSignatureFromTypedData( + ownerPrivateKey, + aWethMsgParams + ); + + const aUsdcNonce = (await aUsdc._nonces(userAddress)).toNumber(); + const aUsdcMsgParams = buildPermitParams( + chainId, + aUsdc.address, + '1', + await aUsdc.name(), + userAddress, + uniswapLiquiditySwapAdapter.address, + aUsdcNonce, + deadline, + amountUSDCtoSwap.toString() + ); + const { v: aUsdcv, r: aUsdcr, s: aUsdcs } = getSignatureFromTypedData( + ownerPrivateKey, + aUsdcMsgParams + ); + const params = buildLiquiditySwapParams( + [dai.address, dai.address], + [expectedDaiAmountForEth, expectedDaiAmountForUsdc], + [0, 0], + [amountWETHtoSwap, amountUSDCtoSwap], + [deadline, deadline], + [aWETHv, aUsdcv], + [aWETHr, aUsdcr], + [aWETHs, aUsdcs], + [false, false] + ); + + await pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address, usdc.address], + [wethFlashloanAmount.toString(), usdcFlashloanAmount.toString()], + [0, 0], + userAddress, + params, + 0 + ); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const userAUsdcBalance = await aUsdc.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); + expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); + expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); + }); + + it('should correctly swap tokens with permit', async () => { + const { + users, + weth, + oracle, + dai, + aDai, + aWETH, + pool, + uniswapLiquiditySwapAdapter, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + + // User will swap liquidity 10 aEth to aDai + const liquidityToSwap = parseEther('10'); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + // Subtract the FL fee from the amount to be swapped 0,09% + const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = (await aWETH._nonces(userAddress)).toNumber(); + const msgParams = buildPermitParams( + chainId, + aWETH.address, + '1', + await aWETH.name(), + userAddress, + uniswapLiquiditySwapAdapter.address, + nonce, + deadline, + liquidityToSwap.toString() + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + const params = buildLiquiditySwapParams( + [dai.address], + [expectedDaiAmount], + [0], + [liquidityToSwap], + [deadline], + [v], + [r], + [s], + [false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params, + 0 + ) + ) + .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') + .withArgs(weth.address, dai.address, flashloanAmount.toString(), expectedDaiAmount); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmount); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); + }); + + it('should revert if inconsistent params', async () => { + const { users, weth, oracle, dai, aWETH, pool, uniswapLiquiditySwapAdapter } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + + // User will swap liquidity 10 aEth to aDai + const liquidityToSwap = parseEther('10'); + await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + + // Subtract the FL fee from the amount to be swapped 0,09% + const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); + + const params = buildLiquiditySwapParams( + [dai.address, weth.address], + [expectedDaiAmount], + [0], + [0], + [0], + [0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + + const params2 = buildLiquiditySwapParams( + [dai.address, weth.address], + [expectedDaiAmount], + [0, 0], + [0, 0], + [0, 0], + [0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params2, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + + const params3 = buildLiquiditySwapParams( + [dai.address, weth.address], + [expectedDaiAmount], + [0, 0], + [0], + [0, 0], + [0, 0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params3, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + + const params4 = buildLiquiditySwapParams( + [dai.address, weth.address], + [expectedDaiAmount], + [0], + [0], + [0], + [0], + [ + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + ], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params4, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + + const params5 = buildLiquiditySwapParams( + [dai.address, weth.address], + [expectedDaiAmount], + [0], + [0], + [0], + [0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [ + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + ], + [false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params5, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + + const params6 = buildLiquiditySwapParams( + [dai.address, weth.address], + [expectedDaiAmount, expectedDaiAmount], + [0], + [0], + [0], + [0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params6, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + + const params7 = buildLiquiditySwapParams( + [dai.address], + [expectedDaiAmount], + [0, 0], + [0], + [0], + [0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params7, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + + const params8 = buildLiquiditySwapParams( + [dai.address], + [expectedDaiAmount], + [0], + [0, 0], + [0], + [0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params8, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + + const params9 = buildLiquiditySwapParams( + [dai.address], + [expectedDaiAmount], + [0], + [0], + [0], + [0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false, false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params9, + 0 + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + }); + + it('should revert if caller not lending pool', async () => { + const { users, weth, oracle, dai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + + // User will swap liquidity 10 aEth to aDai + const liquidityToSwap = parseEther('10'); + await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + + // Subtract the FL fee from the amount to be swapped 0,09% + const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); + + const params = buildLiquiditySwapParams( + [dai.address], + [expectedDaiAmount], + [0], + [0], + [0], + [0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false] + ); + + await expect( + uniswapLiquiditySwapAdapter + .connect(user) + .executeOperation( + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params + ) + ).to.be.revertedWith('CALLER_MUST_BE_LENDING_POOL'); + }); + + it('should work correctly with tokens of different decimals', async () => { + const { + users, + usdc, + oracle, + dai, + aDai, + uniswapLiquiditySwapAdapter, + pool, + deployer, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); + const liquidity = await convertToCurrencyDecimals(usdc.address, '20000'); + + // Provide liquidity + await usdc.mint(liquidity); + await usdc.approve(pool.address, liquidity); + await pool.deposit(usdc.address, liquidity, deployer.address, 0); + + // Make a deposit for user + await usdc.connect(user).mint(amountUSDCtoSwap); + await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); + await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + + const usdcPrice = await oracle.getAssetPrice(usdc.address); + const daiPrice = await oracle.getAssetPrice(dai.address); + + // usdc 6 + const collateralDecimals = (await usdc.decimals()).toString(); + const principalDecimals = (await dai.decimals()).toString(); + + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div( + new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .toFixed(0) + ); + + await mockUniswapRouter.connect(user).setAmountToReturn(usdc.address, expectedDaiAmount); + + const aUsdcData = await pool.getReserveData(usdc.address); + const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + const aUsdcBalance = await aUsdc.balanceOf(userAddress); + await aUsdc.connect(user).approve(uniswapLiquiditySwapAdapter.address, aUsdcBalance); + // Subtract the FL fee from the amount to be swapped 0,09% + const flashloanAmount = new BigNumber(amountUSDCtoSwap.toString()).div(1.0009).toFixed(0); + + const params = buildLiquiditySwapParams( + [dai.address], + [expectedDaiAmount], + [0], + [0], + [0], + [0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [usdc.address], + [flashloanAmount.toString()], + [0], + userAddress, + params, + 0 + ) + ) + .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') + .withArgs(usdc.address, dai.address, flashloanAmount.toString(), expectedDaiAmount); + + const adapterUsdcBalance = await usdc.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const aDaiBalance = await aDai.balanceOf(userAddress); + + expect(adapterUsdcBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(aDaiBalance).to.be.eq(expectedDaiAmount); + }); + + it('should revert when min amount to receive exceeds the max slippage amount', async () => { + const { users, weth, oracle, dai, aWETH, pool, uniswapLiquiditySwapAdapter } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + const smallExpectedDaiAmount = expectedDaiAmount.div(2); + + // User will swap liquidity 10 aEth to aDai + const liquidityToSwap = parseEther('10'); + await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + + // Subtract the FL fee from the amount to be swapped 0,09% + const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); + + const params = buildLiquiditySwapParams( + [dai.address], + [smallExpectedDaiAmount], + [0], + [0], + [0], + [0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false] + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [flashloanAmount.toString()], + [0], + userAddress, + params, + 0 + ) + ).to.be.revertedWith('minAmountOut exceed max slippage'); + }); + + it('should correctly swap tokens all the balance', async () => { + const { + users, + weth, + oracle, + dai, + aDai, + aWETH, + pool, + uniswapLiquiditySwapAdapter, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + + // Remove other balance + await aWETH.connect(user).transfer(users[1].address, parseEther('90')); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + // User will swap liquidity 10 aEth to aDai + const liquidityToSwap = parseEther('10'); + expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); + await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + + const params = buildLiquiditySwapParams( + [dai.address], + [expectedDaiAmount], + [1], + [0], + [0], + [0], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + [false] + ); + + // Flashloan + premium > aToken balance. Then it will only swap the balance - premium + const flashloanFee = liquidityToSwap.mul(9).div(10000); + const swappedAmount = liquidityToSwap.sub(flashloanFee); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [liquidityToSwap.toString()], + [0], + userAddress, + params, + 0 + ) + ) + .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') + .withArgs(weth.address, dai.address, swappedAmount.toString(), expectedDaiAmount); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmount); + expect(userAEthBalance).to.be.eq(Zero); + expect(adapterAEthBalance).to.be.eq(Zero); + }); + + it('should correctly swap tokens all the balance using permit', async () => { + const { + users, + weth, + oracle, + dai, + aDai, + aWETH, + pool, + uniswapLiquiditySwapAdapter, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + + // Remove other balance + await aWETH.connect(user).transfer(users[1].address, parseEther('90')); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + const liquidityToSwap = parseEther('10'); + expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = (await aWETH._nonces(userAddress)).toNumber(); + const msgParams = buildPermitParams( + chainId, + aWETH.address, + '1', + await aWETH.name(), + userAddress, + uniswapLiquiditySwapAdapter.address, + nonce, + deadline, + liquidityToSwap.toString() + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + const params = buildLiquiditySwapParams( + [dai.address], + [expectedDaiAmount], + [1], + [liquidityToSwap], + [deadline], + [v], + [r], + [s], + [false] + ); + + // Flashloan + premium > aToken balance. Then it will only swap the balance - premium + const flashloanFee = liquidityToSwap.mul(9).div(10000); + const swappedAmount = liquidityToSwap.sub(flashloanFee); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address], + [liquidityToSwap.toString()], + [0], + userAddress, + params, + 0 + ) + ) + .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') + .withArgs(weth.address, dai.address, swappedAmount.toString(), expectedDaiAmount); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmount); + expect(userAEthBalance).to.be.eq(Zero); + expect(adapterAEthBalance).to.be.eq(Zero); + }); + }); + + describe('swapAndDeposit', () => { + beforeEach(async () => { + const { users, weth, dai, pool, deployer } = testEnv; + const userAddress = users[0].address; + + // Provide liquidity + await dai.mint(parseEther('20000')); + await dai.approve(pool.address, parseEther('20000')); + await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); + + // Make a deposit for user + await weth.mint(parseEther('100')); + await weth.approve(pool.address, parseEther('100')); + await pool.deposit(weth.address, parseEther('100'), userAddress, 0); + }); + + it('should correctly swap tokens and deposit the out tokens in the pool', async () => { + const { users, weth, oracle, dai, aDai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + + // User will swap liquidity 10 aEth to aDai + const liquidityToSwap = parseEther('10'); + await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + await expect( + uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address], + [dai.address], + [amountWETHtoSwap], + [expectedDaiAmount], + [ + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + ], + [false] + ) + ) + .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') + .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmount); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); + }); + + it('should correctly swap tokens using permit', async () => { + const { users, weth, oracle, dai, aDai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + + // User will swap liquidity 10 aEth to aDai + const liquidityToSwap = parseEther('10'); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = (await aWETH._nonces(userAddress)).toNumber(); + const msgParams = buildPermitParams( + chainId, + aWETH.address, + '1', + await aWETH.name(), + userAddress, + uniswapLiquiditySwapAdapter.address, + nonce, + deadline, + liquidityToSwap.toString() + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await expect( + uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address], + [dai.address], + [amountWETHtoSwap], + [expectedDaiAmount], + [ + { + amount: liquidityToSwap, + deadline, + v, + r, + s, + }, + ], + [false] + ) + ) + .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') + .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmount); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); + }); + + it('should revert if inconsistent params', async () => { + const { users, weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv; + const user = users[0].signer; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await expect( + uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address, dai.address], + [dai.address], + [amountWETHtoSwap], + [expectedDaiAmount], + [ + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + ], + [false] + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + + await expect( + uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address], + [dai.address, weth.address], + [amountWETHtoSwap], + [expectedDaiAmount], + [ + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + ], + [false] + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + + await expect( + uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address], + [dai.address], + [amountWETHtoSwap, amountWETHtoSwap], + [expectedDaiAmount], + [ + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + ], + [false] + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + + await expect( + uniswapLiquiditySwapAdapter + .connect(user) + .swapAndDeposit( + [weth.address], + [dai.address], + [amountWETHtoSwap], + [expectedDaiAmount], + [], + [false] + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + + await expect( + uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address], + [dai.address], + [amountWETHtoSwap], + [expectedDaiAmount, expectedDaiAmount], + [ + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + ], + [false] + ) + ).to.be.revertedWith('INCONSISTENT_PARAMS'); + }); + + it('should revert when min amount to receive exceeds the max slippage amount', async () => { + const { users, weth, oracle, dai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; + const user = users[0].signer; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + const smallExpectedDaiAmount = expectedDaiAmount.div(2); + + // User will swap liquidity 10 aEth to aDai + const liquidityToSwap = parseEther('10'); + await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + + await expect( + uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address], + [dai.address], + [amountWETHtoSwap], + [smallExpectedDaiAmount], + [ + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + ], + [false] + ) + ).to.be.revertedWith('minAmountOut exceed max slippage'); + }); + + it('should correctly swap tokens and deposit multiple tokens', async () => { + const { + users, + weth, + usdc, + oracle, + dai, + aDai, + aWETH, + uniswapLiquiditySwapAdapter, + pool, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmountForEth = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const collateralDecimals = (await usdc.decimals()).toString(); + const principalDecimals = (await dai.decimals()).toString(); + + const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div( + new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .toFixed(0) + ); + + // Make a deposit for user + await usdc.connect(user).mint(amountUSDCtoSwap); + await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); + await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + + const aUsdcData = await pool.getReserveData(usdc.address); + const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); + await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); + + await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountWETHtoSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + await aUsdc.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountUSDCtoSwap); + const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); + + await uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address, usdc.address], + [dai.address, dai.address], + [amountWETHtoSwap, amountUSDCtoSwap], + [expectedDaiAmountForEth, expectedDaiAmountForUsdc], + [ + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + ], + [false, false] + ); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const userAUsdcBalance = await aUsdc.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); + expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); + expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); + }); + + it('should correctly swap tokens and deposit multiple tokens using permit', async () => { + const { + users, + weth, + usdc, + oracle, + dai, + aDai, + aWETH, + uniswapLiquiditySwapAdapter, + pool, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + + const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmountForEth = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const collateralDecimals = (await usdc.decimals()).toString(); + const principalDecimals = (await dai.decimals()).toString(); + + const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div( + new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .toFixed(0) + ); + + // Make a deposit for user + await usdc.connect(user).mint(amountUSDCtoSwap); + await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); + await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + + const aUsdcData = await pool.getReserveData(usdc.address); + const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); + await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); + + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); + + const aWethNonce = (await aWETH._nonces(userAddress)).toNumber(); + const aWethMsgParams = buildPermitParams( + chainId, + aWETH.address, + '1', + await aWETH.name(), + userAddress, + uniswapLiquiditySwapAdapter.address, + aWethNonce, + deadline, + amountWETHtoSwap.toString() + ); + const { v: aWETHv, r: aWETHr, s: aWETHs } = getSignatureFromTypedData( + ownerPrivateKey, + aWethMsgParams + ); + + const aUsdcNonce = (await aUsdc._nonces(userAddress)).toNumber(); + const aUsdcMsgParams = buildPermitParams( + chainId, + aUsdc.address, + '1', + await aUsdc.name(), + userAddress, + uniswapLiquiditySwapAdapter.address, + aUsdcNonce, + deadline, + amountUSDCtoSwap.toString() + ); + const { v: aUsdcv, r: aUsdcr, s: aUsdcs } = getSignatureFromTypedData( + ownerPrivateKey, + aUsdcMsgParams + ); + + await uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address, usdc.address], + [dai.address, dai.address], + [amountWETHtoSwap, amountUSDCtoSwap], + [expectedDaiAmountForEth, expectedDaiAmountForUsdc], + [ + { + amount: amountWETHtoSwap, + deadline, + v: aWETHv, + r: aWETHr, + s: aWETHs, + }, + { + amount: amountUSDCtoSwap, + deadline, + v: aUsdcv, + r: aUsdcr, + s: aUsdcs, + }, + ], + [false, false] + ); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const userAUsdcBalance = await aUsdc.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); + expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); + expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); + }); + + it('should correctly swap all the balance when using a bigger amount', async () => { + const { users, weth, oracle, dai, aDai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + + // Remove other balance + await aWETH.connect(user).transfer(users[1].address, parseEther('90')); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + // User will swap liquidity 10 aEth to aDai + const liquidityToSwap = parseEther('10'); + expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); + + // User will swap liquidity 10 aEth to aDai + await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + + // Only has 10 atokens, so all the balance will be swapped + const bigAmountToSwap = parseEther('100'); + + await expect( + uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address], + [dai.address], + [bigAmountToSwap], + [expectedDaiAmount], + [ + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + ], + [false] + ) + ) + .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') + .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmount); + expect(userAEthBalance).to.be.eq(Zero); + expect(adapterAEthBalance).to.be.eq(Zero); + }); + + it('should correctly swap all the balance when using permit', async () => { + const { users, weth, oracle, dai, aDai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + + // Remove other balance + await aWETH.connect(user).transfer(users[1].address, parseEther('90')); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + // User will swap liquidity 10 aEth to aDai + const liquidityToSwap = parseEther('10'); + expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); + + // Only has 10 atokens, so all the balance will be swapped + const bigAmountToSwap = parseEther('100'); + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + + const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + const aWethNonce = (await aWETH._nonces(userAddress)).toNumber(); + const aWethMsgParams = buildPermitParams( + chainId, + aWETH.address, + '1', + await aWETH.name(), + userAddress, + uniswapLiquiditySwapAdapter.address, + aWethNonce, + deadline, + bigAmountToSwap.toString() + ); + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, aWethMsgParams); + + await expect( + uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address], + [dai.address], + [bigAmountToSwap], + [expectedDaiAmount], + [ + { + amount: bigAmountToSwap, + deadline, + v, + r, + s, + }, + ], + [false] + ) + ) + .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') + .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmount); + expect(userAEthBalance).to.be.eq(Zero); + expect(adapterAEthBalance).to.be.eq(Zero); + }); + }); + }); +}); diff --git a/test-suites/test-aave/uniswapAdapters.repay.spec.ts b/test-suites/test-aave/uniswapAdapters.repay.spec.ts new file mode 100644 index 00000000..c2046cbd --- /dev/null +++ b/test-suites/test-aave/uniswapAdapters.repay.spec.ts @@ -0,0 +1,1469 @@ +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { + convertToCurrencyDecimals, + getContract, + buildPermitParams, + getSignatureFromTypedData, + buildRepayAdapterParams, +} from '../../helpers/contracts-helpers'; +import { getMockUniswapRouter } from '../../helpers/contracts-getters'; +import { deployUniswapRepayAdapter } from '../../helpers/contracts-deployments'; +import { MockUniswapV2Router02 } from '../../types/MockUniswapV2Router02'; +import { Zero } from '@ethersproject/constants'; +import BigNumber from 'bignumber.js'; +import { DRE, evmRevert, evmSnapshot } from '../../helpers/misc-utils'; +import { ethers } from 'ethers'; +import { eContractid } from '../../helpers/types'; +import { StableDebtToken } from '../../types/StableDebtToken'; +import { BUIDLEREVM_CHAINID } from '../../helpers/buidler-constants'; +import { MAX_UINT_AMOUNT } from '../../helpers/constants'; +import { VariableDebtToken } from '../../types'; +const { parseEther } = ethers.utils; + +const { expect } = require('chai'); + +makeSuite('Uniswap adapters', (testEnv: TestEnv) => { + let mockUniswapRouter: MockUniswapV2Router02; + let evmSnapshotId: string; + + before(async () => { + mockUniswapRouter = await getMockUniswapRouter(); + }); + + beforeEach(async () => { + evmSnapshotId = await evmSnapshot(); + }); + + afterEach(async () => { + await evmRevert(evmSnapshotId); + }); + + describe('UniswapRepayAdapter', () => { + beforeEach(async () => { + const { users, weth, dai, usdc, aave, pool, deployer } = testEnv; + const userAddress = users[0].address; + + // Provide liquidity + await dai.mint(parseEther('20000')); + await dai.approve(pool.address, parseEther('20000')); + await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); + + const usdcLiquidity = await convertToCurrencyDecimals(usdc.address, '2000000'); + await usdc.mint(usdcLiquidity); + await usdc.approve(pool.address, usdcLiquidity); + await pool.deposit(usdc.address, usdcLiquidity, deployer.address, 0); + + await weth.mint(parseEther('100')); + await weth.approve(pool.address, parseEther('100')); + await pool.deposit(weth.address, parseEther('100'), deployer.address, 0); + + await aave.mint(parseEther('1000000')); + await aave.approve(pool.address, parseEther('1000000')); + await pool.deposit(aave.address, parseEther('1000000'), deployer.address, 0); + + // Make a deposit for user + await weth.mint(parseEther('1000')); + await weth.approve(pool.address, parseEther('1000')); + await pool.deposit(weth.address, parseEther('1000'), userAddress, 0); + + await aave.mint(parseEther('1000000')); + await aave.approve(pool.address, parseEther('1000000')); + await pool.deposit(aave.address, parseEther('1000000'), userAddress, 0); + + await usdc.mint(usdcLiquidity); + await usdc.approve(pool.address, usdcLiquidity); + await pool.deposit(usdc.address, usdcLiquidity, userAddress, 0); + }); + + describe('constructor', () => { + it('should deploy with correct parameters', async () => { + const { addressesProvider, weth } = testEnv; + await deployUniswapRepayAdapter([ + addressesProvider.address, + mockUniswapRouter.address, + weth.address, + ]); + }); + + it('should revert if not valid addresses provider', async () => { + const { weth } = testEnv; + expect( + deployUniswapRepayAdapter([ + mockUniswapRouter.address, + mockUniswapRouter.address, + weth.address, + ]) + ).to.be.reverted; + }); + }); + + describe('executeOperation', () => { + it('should correctly swap tokens and repay debt', async () => { + const { + users, + pool, + weth, + aWETH, + oracle, + dai, + uniswapRepayAdapter, + helpersContract, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + + const daiStableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).stableDebtTokenAddress; + + const daiStableDebtContract = await getContract( + eContractid.StableDebtToken, + daiStableDebtTokenAddress + ); + + const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + + const liquidityToSwap = amountWETHtoSwap; + await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); + + const flashLoanDebt = new BigNumber(expectedDaiAmount.toString()) + .multipliedBy(1.0009) + .toFixed(0); + + await mockUniswapRouter.setAmountIn( + flashLoanDebt, + weth.address, + dai.address, + liquidityToSwap + ); + + const params = buildRepayAdapterParams( + weth.address, + liquidityToSwap, + 1, + 0, + 0, + 0, + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + false + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapRepayAdapter.address, + [dai.address], + [expectedDaiAmount.toString()], + [0], + userAddress, + params, + 0 + ) + ) + .to.emit(uniswapRepayAdapter, 'Swapped') + .withArgs(weth.address, dai.address, liquidityToSwap.toString(), flashLoanDebt); + + const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); + expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); + }); + + it('should correctly swap tokens and repay debt with permit', async () => { + const { + users, + pool, + weth, + aWETH, + oracle, + dai, + uniswapRepayAdapter, + helpersContract, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + + const daiStableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).stableDebtTokenAddress; + + const daiStableDebtContract = await getContract( + eContractid.StableDebtToken, + daiStableDebtTokenAddress + ); + + const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + + const liquidityToSwap = amountWETHtoSwap; + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = (await aWETH._nonces(userAddress)).toNumber(); + const msgParams = buildPermitParams( + chainId, + aWETH.address, + '1', + await aWETH.name(), + userAddress, + uniswapRepayAdapter.address, + nonce, + deadline, + liquidityToSwap.toString() + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); + + const flashLoanDebt = new BigNumber(expectedDaiAmount.toString()) + .multipliedBy(1.0009) + .toFixed(0); + + await mockUniswapRouter.setAmountIn( + flashLoanDebt, + weth.address, + dai.address, + liquidityToSwap + ); + + const params = buildRepayAdapterParams( + weth.address, + liquidityToSwap, + 1, + liquidityToSwap, + deadline, + v, + r, + s, + false + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapRepayAdapter.address, + [dai.address], + [expectedDaiAmount.toString()], + [0], + userAddress, + params, + 0 + ) + ) + .to.emit(uniswapRepayAdapter, 'Swapped') + .withArgs(weth.address, dai.address, liquidityToSwap.toString(), flashLoanDebt); + + const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); + expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); + }); + + it('should revert if caller not lending pool', async () => { + const { users, pool, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + + const liquidityToSwap = amountWETHtoSwap; + await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); + + const params = buildRepayAdapterParams( + weth.address, + liquidityToSwap, + 1, + 0, + 0, + 0, + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + false + ); + + await expect( + uniswapRepayAdapter + .connect(user) + .executeOperation( + [dai.address], + [expectedDaiAmount.toString()], + [0], + userAddress, + params + ) + ).to.be.revertedWith('CALLER_MUST_BE_LENDING_POOL'); + }); + + it('should revert if there is not debt to repay with the specified rate mode', async () => { + const { users, pool, weth, oracle, dai, uniswapRepayAdapter, aWETH } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + await weth.connect(user).mint(amountWETHtoSwap); + await weth.connect(user).transfer(uniswapRepayAdapter.address, amountWETHtoSwap); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress); + + const liquidityToSwap = amountWETHtoSwap; + await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); + + const params = buildRepayAdapterParams( + weth.address, + liquidityToSwap, + 1, + 0, + 0, + 0, + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + false + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapRepayAdapter.address, + [dai.address], + [expectedDaiAmount.toString()], + [0], + userAddress, + params, + 0 + ) + ).to.be.reverted; + }); + + it('should revert if there is not debt to repay', async () => { + const { users, pool, weth, oracle, dai, uniswapRepayAdapter, aWETH } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + await weth.connect(user).mint(amountWETHtoSwap); + await weth.connect(user).transfer(uniswapRepayAdapter.address, amountWETHtoSwap); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const liquidityToSwap = amountWETHtoSwap; + await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); + + const params = buildRepayAdapterParams( + weth.address, + liquidityToSwap, + 1, + 0, + 0, + 0, + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + false + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapRepayAdapter.address, + [dai.address], + [expectedDaiAmount.toString()], + [0], + userAddress, + params, + 0 + ) + ).to.be.reverted; + }); + + it('should revert when max amount allowed to swap is bigger than max slippage', async () => { + const { users, pool, weth, oracle, dai, aWETH, uniswapRepayAdapter } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + + const bigMaxAmountToSwap = amountWETHtoSwap.mul(2); + await aWETH.connect(user).approve(uniswapRepayAdapter.address, bigMaxAmountToSwap); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, bigMaxAmountToSwap); + + const flashLoanDebt = new BigNumber(expectedDaiAmount.toString()) + .multipliedBy(1.0009) + .toFixed(0); + + await mockUniswapRouter.setAmountIn( + flashLoanDebt, + weth.address, + dai.address, + bigMaxAmountToSwap + ); + + const params = buildRepayAdapterParams( + weth.address, + bigMaxAmountToSwap, + 1, + 0, + 0, + 0, + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + false + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapRepayAdapter.address, + [dai.address], + [expectedDaiAmount.toString()], + [0], + userAddress, + params, + 0 + ) + ).to.be.revertedWith('maxAmountToSwap exceed max slippage'); + }); + + it('should swap, repay debt and pull the needed ATokens leaving no leftovers', async () => { + const { + users, + pool, + weth, + aWETH, + oracle, + dai, + uniswapRepayAdapter, + helpersContract, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + + const daiStableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).stableDebtTokenAddress; + + const daiStableDebtContract = await getContract( + eContractid.StableDebtToken, + daiStableDebtTokenAddress + ); + + const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + + const liquidityToSwap = amountWETHtoSwap; + await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + const userWethBalanceBefore = await weth.balanceOf(userAddress); + + const actualWEthSwapped = new BigNumber(liquidityToSwap.toString()) + .multipliedBy(0.995) + .toFixed(0); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped); + + const flashLoanDebt = new BigNumber(expectedDaiAmount.toString()) + .multipliedBy(1.0009) + .toFixed(0); + + await mockUniswapRouter.setAmountIn( + flashLoanDebt, + weth.address, + dai.address, + actualWEthSwapped + ); + + const params = buildRepayAdapterParams( + weth.address, + liquidityToSwap, + 1, + 0, + 0, + 0, + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + false + ); + + await expect( + pool + .connect(user) + .flashLoan( + uniswapRepayAdapter.address, + [dai.address], + [expectedDaiAmount.toString()], + [0], + userAddress, + params, + 0 + ) + ) + .to.emit(uniswapRepayAdapter, 'Swapped') + .withArgs(weth.address, dai.address, actualWEthSwapped.toString(), flashLoanDebt); + + const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); + const userWethBalance = await weth.balanceOf(userAddress); + + expect(adapterAEthBalance).to.be.eq(Zero); + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); + expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(actualWEthSwapped)); + expect(userWethBalance).to.be.eq(userWethBalanceBefore); + }); + + it('should correctly swap tokens and repay the whole stable debt', async () => { + const { + users, + pool, + weth, + aWETH, + oracle, + dai, + uniswapRepayAdapter, + helpersContract, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + + const daiStableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).stableDebtTokenAddress; + + const daiStableDebtContract = await getContract( + eContractid.StableDebtToken, + daiStableDebtTokenAddress + ); + + const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + + // Add a % to repay on top of the debt + const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString()) + .multipliedBy(1.1) + .toFixed(0); + + await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + // Add a % to repay on top of the debt + const amountToRepay = new BigNumber(expectedDaiAmount.toString()) + .multipliedBy(1.1) + .toFixed(0); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap); + await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap); + + const params = buildRepayAdapterParams( + weth.address, + liquidityToSwap, + 1, + 0, + 0, + 0, + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + false + ); + + await pool + .connect(user) + .flashLoan( + uniswapRepayAdapter.address, + [dai.address], + [amountToRepay.toString()], + [0], + userAddress, + params, + 0 + ); + + const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); + + expect(adapterAEthBalance).to.be.eq(Zero); + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); + expect(userDaiStableDebtAmount).to.be.eq(Zero); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); + }); + + it('should correctly swap tokens and repay the whole variable debt', async () => { + const { + users, + pool, + weth, + aWETH, + oracle, + dai, + uniswapRepayAdapter, + helpersContract, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress); + + const daiStableVariableTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).variableDebtTokenAddress; + + const daiVariableDebtContract = await getContract( + eContractid.VariableDebtToken, + daiStableVariableTokenAddress + ); + + const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( + userAddress + ); + + // Add a % to repay on top of the debt + const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString()) + .multipliedBy(1.1) + .toFixed(0); + + await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + // Add a % to repay on top of the debt + const amountToRepay = new BigNumber(expectedDaiAmount.toString()) + .multipliedBy(1.1) + .toFixed(0); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap); + await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap); + + const params = buildRepayAdapterParams( + weth.address, + liquidityToSwap, + 2, + 0, + 0, + 0, + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + false + ); + + await pool + .connect(user) + .flashLoan( + uniswapRepayAdapter.address, + [dai.address], + [amountToRepay.toString()], + [0], + userAddress, + params, + 0 + ); + + const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); + + expect(adapterAEthBalance).to.be.eq(Zero); + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(userDaiVariableDebtAmountBefore).to.be.gte(expectedDaiAmount); + expect(userDaiVariableDebtAmount).to.be.eq(Zero); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); + }); + + it('should correctly repay debt via flash loan using the same asset as collateral', async () => { + const { users, pool, aDai, dai, uniswapRepayAdapter, helpersContract } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + // Add deposit for user + await dai.mint(parseEther('30')); + await dai.approve(pool.address, parseEther('30')); + await pool.deposit(dai.address, parseEther('30'), userAddress, 0); + + const amountCollateralToSwap = parseEther('10'); + const debtAmount = parseEther('10'); + + // Open user Debt + await pool.connect(user).borrow(dai.address, debtAmount, 2, 0, userAddress); + + const daiVariableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).variableDebtTokenAddress; + + const daiVariableDebtContract = await getContract( + eContractid.VariableDebtToken, + daiVariableDebtTokenAddress + ); + + const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( + userAddress + ); + + const flashLoanDebt = new BigNumber(amountCollateralToSwap.toString()) + .multipliedBy(1.0009) + .toFixed(0); + + await aDai.connect(user).approve(uniswapRepayAdapter.address, flashLoanDebt); + const userADaiBalanceBefore = await aDai.balanceOf(userAddress); + const userDaiBalanceBefore = await dai.balanceOf(userAddress); + + const params = buildRepayAdapterParams( + dai.address, + amountCollateralToSwap, + 2, + 0, + 0, + 0, + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + false + ); + + await pool + .connect(user) + .flashLoan( + uniswapRepayAdapter.address, + [dai.address], + [amountCollateralToSwap.toString()], + [0], + userAddress, + params, + 0 + ); + + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); + const userADaiBalance = await aDai.balanceOf(userAddress); + const adapterADaiBalance = await aDai.balanceOf(uniswapRepayAdapter.address); + const userDaiBalance = await dai.balanceOf(userAddress); + + expect(adapterADaiBalance).to.be.eq(Zero, 'adapter aDAI balance should be zero'); + expect(adapterDaiBalance).to.be.eq(Zero, 'adapter DAI balance should be zero'); + expect(userDaiVariableDebtAmountBefore).to.be.gte( + debtAmount, + ' user DAI variable debt before should be gte debtAmount' + ); + expect(userDaiVariableDebtAmount).to.be.lt( + debtAmount, + 'user dai variable debt amount should be lt debt amount' + ); + expect(userADaiBalance).to.be.lt( + userADaiBalanceBefore, + 'user aDAI balance should be lt aDAI prior balance' + ); + expect(userADaiBalance).to.be.gte( + userADaiBalanceBefore.sub(flashLoanDebt), + 'user aDAI balance should be gte aDAI prior balance sub flash loan debt' + ); + expect(userDaiBalance).to.be.eq(userDaiBalanceBefore, 'user dai balance eq prior balance'); + }); + }); + + describe('swapAndRepay', () => { + it('should correctly swap tokens and repay debt', async () => { + const { + users, + pool, + weth, + aWETH, + oracle, + dai, + uniswapRepayAdapter, + helpersContract, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + + const daiStableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).stableDebtTokenAddress; + + const daiStableDebtContract = await getContract( + eContractid.StableDebtToken, + daiStableDebtTokenAddress + ); + + const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + + const liquidityToSwap = amountWETHtoSwap; + await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap); + + await mockUniswapRouter.setDefaultMockValue(liquidityToSwap); + + await uniswapRepayAdapter.connect(user).swapAndRepay( + weth.address, + dai.address, + liquidityToSwap, + expectedDaiAmount, + 1, + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + false + ); + + const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); + expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); + }); + + it('should correctly swap tokens and repay debt with permit', async () => { + const { + users, + pool, + weth, + aWETH, + oracle, + dai, + uniswapRepayAdapter, + helpersContract, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + + const daiStableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).stableDebtTokenAddress; + + const daiStableDebtContract = await getContract( + eContractid.StableDebtToken, + daiStableDebtTokenAddress + ); + + const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + + const liquidityToSwap = amountWETHtoSwap; + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap); + + await mockUniswapRouter.setDefaultMockValue(liquidityToSwap); + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = (await aWETH._nonces(userAddress)).toNumber(); + const msgParams = buildPermitParams( + chainId, + aWETH.address, + '1', + await aWETH.name(), + userAddress, + uniswapRepayAdapter.address, + nonce, + deadline, + liquidityToSwap.toString() + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await uniswapRepayAdapter.connect(user).swapAndRepay( + weth.address, + dai.address, + liquidityToSwap, + expectedDaiAmount, + 1, + { + amount: liquidityToSwap, + deadline, + v, + r, + s, + }, + false + ); + + const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); + expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); + }); + + it('should revert if there is not debt to repay', async () => { + const { users, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv; + const user = users[0].signer; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const liquidityToSwap = amountWETHtoSwap; + await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + + await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap); + + await mockUniswapRouter.setDefaultMockValue(liquidityToSwap); + + await expect( + uniswapRepayAdapter.connect(user).swapAndRepay( + weth.address, + dai.address, + liquidityToSwap, + expectedDaiAmount, + 1, + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + false + ) + ).to.be.reverted; + }); + + it('should revert when max amount allowed to swap is bigger than max slippage', async () => { + const { users, pool, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + + const bigMaxAmountToSwap = amountWETHtoSwap.mul(2); + await aWETH.connect(user).approve(uniswapRepayAdapter.address, bigMaxAmountToSwap); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, bigMaxAmountToSwap); + + await mockUniswapRouter.setDefaultMockValue(bigMaxAmountToSwap); + + await expect( + uniswapRepayAdapter.connect(user).swapAndRepay( + weth.address, + dai.address, + bigMaxAmountToSwap, + expectedDaiAmount, + 1, + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + false + ) + ).to.be.revertedWith('maxAmountToSwap exceed max slippage'); + }); + + it('should swap, repay debt and pull the needed ATokens leaving no leftovers', async () => { + const { + users, + pool, + weth, + aWETH, + oracle, + dai, + uniswapRepayAdapter, + helpersContract, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + + const daiStableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).stableDebtTokenAddress; + + const daiStableDebtContract = await getContract( + eContractid.StableDebtToken, + daiStableDebtTokenAddress + ); + + const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + + const liquidityToSwap = amountWETHtoSwap; + await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + const userWethBalanceBefore = await weth.balanceOf(userAddress); + + const actualWEthSwapped = new BigNumber(liquidityToSwap.toString()) + .multipliedBy(0.995) + .toFixed(0); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped); + + await mockUniswapRouter.setDefaultMockValue(actualWEthSwapped); + + await uniswapRepayAdapter.connect(user).swapAndRepay( + weth.address, + dai.address, + liquidityToSwap, + expectedDaiAmount, + 1, + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + false + ); + + const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); + const userWethBalance = await weth.balanceOf(userAddress); + + expect(adapterAEthBalance).to.be.eq(Zero); + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); + expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(actualWEthSwapped)); + expect(userWethBalance).to.be.eq(userWethBalanceBefore); + }); + + it('should correctly swap tokens and repay the whole stable debt', async () => { + const { + users, + pool, + weth, + aWETH, + oracle, + dai, + uniswapRepayAdapter, + helpersContract, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + + const daiStableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).stableDebtTokenAddress; + + const daiStableDebtContract = await getContract( + eContractid.StableDebtToken, + daiStableDebtTokenAddress + ); + + const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + + // Add a % to repay on top of the debt + const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString()) + .multipliedBy(1.1) + .toFixed(0); + + await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + // Add a % to repay on top of the debt + const amountToRepay = new BigNumber(expectedDaiAmount.toString()) + .multipliedBy(1.1) + .toFixed(0); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap); + await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap); + + await uniswapRepayAdapter.connect(user).swapAndRepay( + weth.address, + dai.address, + liquidityToSwap, + amountToRepay, + 1, + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + false + ); + + const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); + + expect(adapterAEthBalance).to.be.eq(Zero); + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); + expect(userDaiStableDebtAmount).to.be.eq(Zero); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); + }); + + it('should correctly swap tokens and repay the whole variable debt', async () => { + const { + users, + pool, + weth, + aWETH, + oracle, + dai, + uniswapRepayAdapter, + helpersContract, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmount = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress); + + const daiStableVariableTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).variableDebtTokenAddress; + + const daiVariableDebtContract = await getContract( + eContractid.VariableDebtToken, + daiStableVariableTokenAddress + ); + + const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( + userAddress + ); + + // Add a % to repay on top of the debt + const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString()) + .multipliedBy(1.1) + .toFixed(0); + + await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + + // Add a % to repay on top of the debt + const amountToRepay = new BigNumber(expectedDaiAmount.toString()) + .multipliedBy(1.1) + .toFixed(0); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap); + await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap); + + await uniswapRepayAdapter.connect(user).swapAndRepay( + weth.address, + dai.address, + liquidityToSwap, + amountToRepay, + 2, + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + false + ); + + const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); + + expect(adapterAEthBalance).to.be.eq(Zero); + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(userDaiVariableDebtAmountBefore).to.be.gte(expectedDaiAmount); + expect(userDaiVariableDebtAmount).to.be.eq(Zero); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); + }); + + it('should correctly repay debt using the same asset as collateral', async () => { + const { users, pool, dai, uniswapRepayAdapter, helpersContract, aDai } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + // Add deposit for user + await dai.mint(parseEther('30')); + await dai.approve(pool.address, parseEther('30')); + await pool.deposit(dai.address, parseEther('30'), userAddress, 0); + + const amountCollateralToSwap = parseEther('4'); + + const debtAmount = parseEther('3'); + + // Open user Debt + await pool.connect(user).borrow(dai.address, debtAmount, 2, 0, userAddress); + + const daiVariableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).variableDebtTokenAddress; + + const daiVariableDebtContract = await getContract( + eContractid.StableDebtToken, + daiVariableDebtTokenAddress + ); + + const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( + userAddress + ); + + await aDai.connect(user).approve(uniswapRepayAdapter.address, amountCollateralToSwap); + const userADaiBalanceBefore = await aDai.balanceOf(userAddress); + const userDaiBalanceBefore = await dai.balanceOf(userAddress); + + await uniswapRepayAdapter.connect(user).swapAndRepay( + dai.address, + dai.address, + amountCollateralToSwap, + amountCollateralToSwap, + 2, + { + amount: 0, + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + false + ); + + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); + const userADaiBalance = await aDai.balanceOf(userAddress); + const adapterADaiBalance = await aDai.balanceOf(uniswapRepayAdapter.address); + const userDaiBalance = await dai.balanceOf(userAddress); + + expect(adapterADaiBalance).to.be.eq(Zero, 'adapter aADAI should be zero'); + expect(adapterDaiBalance).to.be.eq(Zero, 'adapter DAI should be zero'); + expect(userDaiVariableDebtAmountBefore).to.be.gte( + debtAmount, + 'user dai variable debt before should be gte debtAmount' + ); + expect(userDaiVariableDebtAmount).to.be.lt( + debtAmount, + 'current user dai variable debt amount should be less than debtAmount' + ); + expect(userADaiBalance).to.be.lt( + userADaiBalanceBefore, + 'current user aDAI balance should be less than prior balance' + ); + expect(userADaiBalance).to.be.gte( + userADaiBalanceBefore.sub(amountCollateralToSwap), + 'current user aDAI balance should be gte user balance sub swapped collateral' + ); + expect(userDaiBalance).to.be.eq( + userDaiBalanceBefore, + 'user DAI balance should remain equal' + ); + }); + }); + }); +}); diff --git a/test-suites/test-aave/upgradeability.spec.ts b/test-suites/test-aave/upgradeability.spec.ts new file mode 100644 index 00000000..74e02325 --- /dev/null +++ b/test-suites/test-aave/upgradeability.spec.ts @@ -0,0 +1,234 @@ +import { expect } from 'chai'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors, eContractid } from '../../helpers/types'; +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, + getMockStableDebtToken, + getMockVariableDebtToken, + getStableDebtToken, + getVariableDebtToken, +} from '../../helpers/contracts-getters'; +import { + deployMockAToken, + deployMockStableDebtToken, + deployMockVariableDebtToken, +} from '../../helpers/contracts-deployments'; + +makeSuite('Upgradeability', (testEnv: TestEnv) => { + const { CALLER_NOT_POOL_ADMIN } = ProtocolErrors; + let newATokenAddress: string; + let newStableTokenAddress: string; + let newVariableTokenAddress: string; + + before('deploying instances', async () => { + const { dai, pool } = testEnv; + const aTokenInstance = await deployMockAToken([ + pool.address, + dai.address, + ZERO_ADDRESS, + ZERO_ADDRESS, + 'Aave Interest bearing DAI updated', + 'aDAI', + ]); + + const stableDebtTokenInstance = await deployMockStableDebtToken([ + pool.address, + dai.address, + ZERO_ADDRESS, + 'Aave stable debt bearing DAI updated', + 'stableDebtDAI', + ]); + + const variableDebtTokenInstance = await deployMockVariableDebtToken([ + pool.address, + dai.address, + ZERO_ADDRESS, + 'Aave variable debt bearing DAI updated', + 'variableDebtDAI', + ]); + + newATokenAddress = aTokenInstance.address; + newVariableTokenAddress = variableDebtTokenInstance.address; + newStableTokenAddress = stableDebtTokenInstance.address; + }); + + it('Tries to update the DAI Atoken implementation with a different address than the lendingPoolManager', async () => { + const { dai, configurator, users } = testEnv; + + const name = await (await getAToken(newATokenAddress)).name(); + const symbol = await (await getAToken(newATokenAddress)).symbol(); + + const updateATokenInputParams: { + asset: string; + treasury: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + treasury: ZERO_ADDRESS, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newATokenAddress, + }; + await expect( + configurator.connect(users[1].signer).updateAToken(updateATokenInputParams) + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Upgrades the DAI Atoken implementation ', async () => { + const { dai, configurator, aDai } = testEnv; + + const name = await (await getAToken(newATokenAddress)).name(); + const symbol = await (await getAToken(newATokenAddress)).symbol(); + + const updateATokenInputParams: { + asset: string; + treasury: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + treasury: ZERO_ADDRESS, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newATokenAddress, + }; + await configurator.updateAToken(updateATokenInputParams); + + const tokenName = await aDai.name(); + + expect(tokenName).to.be.eq('Aave Interest bearing DAI updated', 'Invalid token name'); + }); + + it('Tries to update the DAI Stable debt token implementation with a different address than the lendingPoolManager', async () => { + const { dai, configurator, users } = testEnv; + + const name = await (await getStableDebtToken(newStableTokenAddress)).name(); + const symbol = await (await getStableDebtToken(newStableTokenAddress)).symbol(); + + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newStableTokenAddress, + } + + await expect( + configurator + .connect(users[1].signer) + .updateStableDebtToken(updateDebtTokenInput) + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Upgrades the DAI stable debt token implementation ', async () => { + const { dai, configurator, pool, helpersContract } = testEnv; + + const name = await (await getStableDebtToken(newStableTokenAddress)).name(); + const symbol = await (await getStableDebtToken(newStableTokenAddress)).symbol(); + + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newStableTokenAddress, + } + + await configurator.updateStableDebtToken(updateDebtTokenInput); + + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses(dai.address); + + const debtToken = await getMockStableDebtToken(stableDebtTokenAddress); + + const tokenName = await debtToken.name(); + + expect(tokenName).to.be.eq('Aave stable debt bearing DAI updated', 'Invalid token name'); + }); + + it('Tries to update the DAI variable debt token implementation with a different address than the lendingPoolManager', async () => { + const {dai, configurator, users} = testEnv; + + const name = await (await getVariableDebtToken(newVariableTokenAddress)).name(); + const symbol = await (await getVariableDebtToken(newVariableTokenAddress)).symbol(); + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newVariableTokenAddress, + } + + await expect( + configurator + .connect(users[1].signer) + .updateVariableDebtToken(updateDebtTokenInput) + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Upgrades the DAI variable debt token implementation ', async () => { + const {dai, configurator, pool, helpersContract} = testEnv; + + const name = await (await getVariableDebtToken(newVariableTokenAddress)).name(); + const symbol = await (await getVariableDebtToken(newVariableTokenAddress)).symbol(); + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newVariableTokenAddress, + } + //const name = await (await getAToken(newATokenAddress)).name(); + + await configurator.updateVariableDebtToken(updateDebtTokenInput); + + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + dai.address + ); + + const debtToken = await getMockVariableDebtToken(variableDebtTokenAddress); + + const tokenName = await debtToken.name(); + + expect(tokenName).to.be.eq('Aave variable debt bearing DAI updated', 'Invalid token name'); + }); +}); diff --git a/test-suites/test-aave/variable-debt-token.spec.ts b/test-suites/test-aave/variable-debt-token.spec.ts new file mode 100644 index 00000000..d4afbbf0 --- /dev/null +++ b/test-suites/test-aave/variable-debt-token.spec.ts @@ -0,0 +1,36 @@ +import { expect } from 'chai'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors, TokenContractId, eContractid } from '../../helpers/types'; +import { getVariableDebtToken } from '../../helpers/contracts-getters'; + +makeSuite('Variable debt token tests', (testEnv: TestEnv) => { + const { CT_CALLER_MUST_BE_LENDING_POOL } = ProtocolErrors; + + it('Tries to invoke mint not being the LendingPool', async () => { + const { deployer, pool, dai, helpersContract } = testEnv; + + const daiVariableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).variableDebtTokenAddress; + + const variableDebtContract = await getVariableDebtToken(daiVariableDebtTokenAddress); + + await expect( + variableDebtContract.mint(deployer.address, deployer.address, '1', '1') + ).to.be.revertedWith(CT_CALLER_MUST_BE_LENDING_POOL); + }); + + it('Tries to invoke burn not being the LendingPool', async () => { + const { deployer, pool, dai, helpersContract } = testEnv; + + const daiVariableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).variableDebtTokenAddress; + + const variableDebtContract = await getVariableDebtToken(daiVariableDebtTokenAddress); + + await expect(variableDebtContract.burn(deployer.address, '1', '1')).to.be.revertedWith( + CT_CALLER_MUST_BE_LENDING_POOL + ); + }); +}); diff --git a/test-suites/test-aave/weth-gateway.spec.ts b/test-suites/test-aave/weth-gateway.spec.ts new file mode 100644 index 00000000..22939f5c --- /dev/null +++ b/test-suites/test-aave/weth-gateway.spec.ts @@ -0,0 +1,370 @@ +import { MAX_UINT_AMOUNT } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { parseEther } from 'ethers/lib/utils'; +import { DRE, waitForTx } from '../../helpers/misc-utils'; +import { BigNumber } from 'ethers'; +import { getStableDebtToken, getVariableDebtToken } from '../../helpers/contracts-getters'; +import { deploySelfdestructTransferMock } from '../../helpers/contracts-deployments'; + +const { expect } = require('chai'); + +makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => { + const zero = BigNumber.from('0'); + const depositSize = parseEther('5'); + const daiSize = parseEther('10000'); + it('Deposit WETH via WethGateway and DAI', async () => { + const { users, wethGateway, aWETH } = testEnv; + + const user = users[1]; + const depositor = users[0]; + + // Deposit liquidity with native ETH + await wethGateway + .connect(depositor.signer) + .depositETH(depositor.address, '0', { value: depositSize }); + + // Deposit with native ETH + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(depositSize); + }); + + it('Withdraw WETH - Partial', async () => { + const { users, wethGateway, aWETH, pool } = testEnv; + + const user = users[1]; + const priorEthersBalance = await user.signer.getBalance(); + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.'); + + // Partially withdraw native ETH + const partialWithdraw = await convertToCurrencyDecimals(aWETH.address, '2'); + + // Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether + const approveTx = await aWETH + .connect(user.signer) + .approve(wethGateway.address, MAX_UINT_AMOUNT); + const { gasUsed: approveGas } = await waitForTx(approveTx); + + // Partial Withdraw and send native Ether to user + const { gasUsed: withdrawGas } = await waitForTx( + await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) + ); + + const afterPartialEtherBalance = await user.signer.getBalance(); + const afterPartialATokensBalance = await aWETH.balanceOf(user.address); + const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice); + + expect(afterPartialEtherBalance).to.be.equal( + priorEthersBalance.add(partialWithdraw).sub(gasCosts), + 'User ETHER balance should contain the partial withdraw' + ); + expect(afterPartialATokensBalance).to.be.equal( + aTokensBalance.sub(partialWithdraw), + 'User aWETH balance should be substracted' + ); + }); + + it('Withdraw WETH - Full', async () => { + const { users, aWETH, wethGateway, pool } = testEnv; + + const user = users[1]; + const priorEthersBalance = await user.signer.getBalance(); + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.'); + + // Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether + const approveTx = await aWETH + .connect(user.signer) + .approve(wethGateway.address, MAX_UINT_AMOUNT); + const { gasUsed: approveGas } = await waitForTx(approveTx); + + // Full withdraw + const { gasUsed: withdrawGas } = await waitForTx( + await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) + ); + + const afterFullEtherBalance = await user.signer.getBalance(); + const afterFullATokensBalance = await aWETH.balanceOf(user.address); + const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice); + + expect(afterFullEtherBalance).to.be.eq( + priorEthersBalance.add(aTokensBalance).sub(gasCosts), + 'User ETHER balance should contain the full withdraw' + ); + expect(afterFullATokensBalance).to.be.eq(0, 'User aWETH balance should be zero'); + }); + + it('Borrow stable WETH and Full Repay with ETH', async () => { + const { users, wethGateway, aDai, weth, dai, pool, helpersContract } = testEnv; + const borrowSize = parseEther('1'); + const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); + const user = users[1]; + const depositor = users[0]; + + // Deposit with native ETH + await wethGateway + .connect(depositor.signer) + .depositETH(depositor.address, '0', { value: depositSize }); + + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const stableDebtToken = await getStableDebtToken(stableDebtTokenAddress); + + // Deposit 10000 DAI + await dai.connect(user.signer).mint(daiSize); + await dai.connect(user.signer).approve(pool.address, daiSize); + await pool.connect(user.signer).deposit(dai.address, daiSize, user.address, '0'); + + const aTokensBalance = await aDai.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(daiSize); + + // Borrow WETH with WETH as collateral + await waitForTx( + await pool.connect(user.signer).borrow(weth.address, borrowSize, '1', '0', user.address) + ); + + const debtBalance = await stableDebtToken.balanceOf(user.address); + + expect(debtBalance).to.be.gt(zero); + + // Full Repay WETH with native ETH + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) + ); + + const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); + expect(debtBalanceAfterRepay).to.be.eq(zero); + + // Withdraw DAI + await aDai.connect(user.signer).approve(pool.address, MAX_UINT_AMOUNT); + await pool.connect(user.signer).withdraw(dai.address, MAX_UINT_AMOUNT, user.address); + }); + + it('Borrow variable WETH and Full Repay with ETH', async () => { + const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; + const borrowSize = parseEther('1'); + const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); + const user = users[1]; + + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + // Deposit with native ETH + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(depositSize); + + // Borrow WETH with WETH as collateral + await waitForTx( + await pool.connect(user.signer).borrow(weth.address, borrowSize, '2', '0', user.address) + ); + + const debtBalance = await varDebtToken.balanceOf(user.address); + + expect(debtBalance).to.be.gt(zero); + + // Partial Repay WETH loan with native ETH + const partialPayment = repaySize.div(2); + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(partialPayment, '2', user.address, { value: partialPayment }) + ); + + const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); + expect(debtBalanceAfterPartialRepay).to.be.lt(debtBalance); + + // Full Repay WETH loan with native ETH + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) + ); + const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); + expect(debtBalanceAfterFullRepay).to.be.eq(zero); + }); + + it('Borrow ETH via delegateApprove ETH and repays back', async () => { + const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; + const borrowSize = parseEther('1'); + const user = users[2]; + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + const priorDebtBalance = await varDebtToken.balanceOf(user.address); + expect(priorDebtBalance).to.be.eq(zero); + + // Deposit WETH with native ETH + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(depositSize); + + // Delegates borrowing power of WETH to WETHGateway + await waitForTx( + await varDebtToken.connect(user.signer).approveDelegation(wethGateway.address, borrowSize) + ); + + // Borrows ETH with WETH as collateral + await waitForTx(await wethGateway.connect(user.signer).borrowETH(borrowSize, '2', '0')); + + const debtBalance = await varDebtToken.balanceOf(user.address); + + expect(debtBalance).to.be.gt(zero); + + // Full Repay WETH loan with native ETH + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) + ); + const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); + expect(debtBalanceAfterFullRepay).to.be.eq(zero); + }); + + it('Should revert if receiver function receives Ether if not WETH', async () => { + const { users, wethGateway } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + + // Call receiver function (empty data + value) + await expect( + user.signer.sendTransaction({ + to: wethGateway.address, + value: amount, + gasLimit: DRE.network.config.gas, + }) + ).to.be.revertedWith('Receive not allowed'); + }); + + it('Should revert if fallback functions is called with Ether', async () => { + const { users, wethGateway } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + const fakeABI = ['function wantToCallFallback()']; + const abiCoder = new DRE.ethers.utils.Interface(fakeABI); + const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []); + + // Call fallback function with value + await expect( + user.signer.sendTransaction({ + to: wethGateway.address, + data: fakeMethodEncoded, + value: amount, + gasLimit: DRE.network.config.gas, + }) + ).to.be.revertedWith('Fallback not allowed'); + }); + + it('Should revert if fallback functions is called', async () => { + const { users, wethGateway } = testEnv; + const user = users[0]; + + const fakeABI = ['function wantToCallFallback()']; + const abiCoder = new DRE.ethers.utils.Interface(fakeABI); + const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []); + + // Call fallback function without value + await expect( + user.signer.sendTransaction({ + to: wethGateway.address, + data: fakeMethodEncoded, + gasLimit: DRE.network.config.gas, + }) + ).to.be.revertedWith('Fallback not allowed'); + }); + + it('Getters should retrieve correct state', async () => { + const { aWETH, weth, pool, wethGateway } = testEnv; + + const WETHAddress = await wethGateway.getWETHAddress(); + const aWETHAddress = await wethGateway.getAWETHAddress(); + const poolAddress = await wethGateway.getLendingPoolAddress(); + + expect(WETHAddress).to.be.equal(weth.address); + expect(aWETHAddress).to.be.equal(aWETH.address); + expect(poolAddress).to.be.equal(pool.address); + }); + + it('Owner can do emergency token recovery', async () => { + const { users, dai, wethGateway, deployer } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + + await dai.connect(user.signer).mint(amount); + const daiBalanceAfterMint = await dai.balanceOf(user.address); + + await dai.connect(user.signer).transfer(wethGateway.address, amount); + const daiBalanceAfterBadTransfer = await dai.balanceOf(user.address); + expect(daiBalanceAfterBadTransfer).to.be.eq( + daiBalanceAfterMint.sub(amount), + 'User should have lost the funds here.' + ); + + await wethGateway + .connect(deployer.signer) + .emergencyTokenTransfer(dai.address, user.address, amount); + const daiBalanceAfterRecovery = await dai.balanceOf(user.address); + + expect(daiBalanceAfterRecovery).to.be.eq( + daiBalanceAfterMint, + 'User should recover the funds due emergency token transfer' + ); + }); + + it('Owner can do emergency native ETH recovery', async () => { + const { users, wethGateway, deployer } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + const userBalancePriorCall = await user.signer.getBalance(); + + // Deploy contract with payable selfdestruct contract + const selfdestructContract = await deploySelfdestructTransferMock(); + + // Selfdestruct the mock, pointing to WETHGateway address + const callTx = await selfdestructContract + .connect(user.signer) + .destroyAndTransfer(wethGateway.address, { value: amount }); + const { gasUsed } = await waitForTx(callTx); + const gasFees = gasUsed.mul(callTx.gasPrice); + const userBalanceAfterCall = await user.signer.getBalance(); + + expect(userBalanceAfterCall).to.be.eq(userBalancePriorCall.sub(amount).sub(gasFees), ''); + ('User should have lost the funds'); + + // Recover the funds from the contract and sends back to the user + await wethGateway.connect(deployer.signer).emergencyEtherTransfer(user.address, amount); + + const userBalanceAfterRecovery = await user.signer.getBalance(); + const wethGatewayAfterRecovery = await DRE.ethers.provider.getBalance(wethGateway.address); + + expect(userBalanceAfterRecovery).to.be.eq( + userBalancePriorCall.sub(gasFees), + 'User should recover the funds due emergency eth transfer.' + ); + expect(wethGatewayAfterRecovery).to.be.eq('0', 'WETHGateway ether balance should be zero.'); + }); +}); diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-lp/__setup.spec.ts new file mode 100644 index 00000000..45190ee6 --- /dev/null +++ b/test-suites/test-lp/__setup.spec.ts @@ -0,0 +1,292 @@ +import rawBRE from 'hardhat'; +import { MockContract } from 'ethereum-waffle'; +import { + insertContractAddressInDb, + getEthersSigners, + registerContractInJsonDb, +} from '../../helpers/contracts-helpers'; +import { + deployLendingPoolAddressesProvider, + deployMintableERC20, + deployLendingPoolAddressesProviderRegistry, + deployLendingPoolConfigurator, + deployLendingPool, + deployPriceOracle, + deployAaveOracle, + deployLendingPoolCollateralManager, + deployMockFlashLoanReceiver, + deployWalletBalancerProvider, + deployAaveProtocolDataProvider, + deployLendingRateOracle, + deployStableAndVariableTokensHelper, + deployATokensAndRatesHelper, + deployWETHGateway, + deployWETHMocked, + deployMockUniswapRouter, + deployUniswapLiquiditySwapAdapter, + deployUniswapRepayAdapter, + deployFlashLiquidationAdapter, +} from '../../helpers/contracts-deployments'; +import { Signer } from 'ethers'; +import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types'; +import { MintableERC20 } from '../../types/MintableERC20'; +import { + ConfigNames, + getReservesConfigByPool, + getTreasuryAddress, + loadPoolConfig, +} from '../../helpers/configuration'; +import { initializeMakeSuite } from './helpers/make-suite'; + +import { + setInitialAssetPricesInOracle, + deployAllMockAggregators, + setInitialMarketRatesInRatesOracleByHelper, +} from '../../helpers/oracles-helpers'; +import { DRE, waitForTx } from '../../helpers/misc-utils'; +import { initReservesByHelper, configureReservesByHelper } from '../../helpers/init-helpers'; +import UniswapConfig from '../../markets/uniswap'; +import { ZERO_ADDRESS } from '../../helpers/constants'; +import { + getLendingPool, + getLendingPoolConfiguratorProxy, + getPairsTokenAggregator, +} from '../../helpers/contracts-getters'; +import { WETH9Mocked } from '../../types/WETH9Mocked'; + +const MOCK_USD_PRICE_IN_WEI = UniswapConfig.ProtocolGlobalParams.MockUsdPriceInWei; +const ALL_ASSETS_INITIAL_PRICES = UniswapConfig.Mocks.AllAssetsInitialPrices; +const USD_ADDRESS = UniswapConfig.ProtocolGlobalParams.UsdAddress; +const MOCK_CHAINLINK_AGGREGATORS_PRICES = UniswapConfig.Mocks.AllAssetsInitialPrices; +const LENDING_RATE_ORACLE_RATES_COMMON = UniswapConfig.LendingRateOracleRatesCommon; + +const deployAllMockTokens = async (deployer: Signer) => { + const tokens: { [symbol: string]: MockContract | MintableERC20 | WETH9Mocked } = {}; + + const uniswapConfigData = getReservesConfigByPool(AavePools.uniswap); + + for (const tokenSymbol of Object.keys(TokenContractId)) { + if (tokenSymbol === 'UniWETH') { + tokens[tokenSymbol] = await deployWETHMocked(); + await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); + continue; + } + let decimals = 18; + + let configData = (uniswapConfigData)[tokenSymbol]; + + if (!configData) { + decimals = 18; + } + + tokens[tokenSymbol] = await deployMintableERC20([ + tokenSymbol, + tokenSymbol, + configData ? configData.reserveDecimals : 18, + ]); + await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); + } + + return tokens; +}; + +const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { + console.time('setup'); + const aaveAdmin = await deployer.getAddress(); + + const mockTokens = await deployAllMockTokens(deployer); + + const addressesProvider = await deployLendingPoolAddressesProvider(UniswapConfig.MarketId); + await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin)); + + //setting users[1] as emergency admin, which is in position 2 in the DRE addresses list + const addressList = await Promise.all( + (await DRE.ethers.getSigners()).map((signer) => signer.getAddress()) + ); + + await waitForTx(await addressesProvider.setEmergencyAdmin(addressList[2])); + + const addressesProviderRegistry = await deployLendingPoolAddressesProviderRegistry(); + await waitForTx( + await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 1) + ); + + const lendingPoolImpl = await deployLendingPool(); + + await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address)); + + const lendingPoolAddress = await addressesProvider.getLendingPool(); + const lendingPoolProxy = await getLendingPool(lendingPoolAddress); + + await insertContractAddressInDb(eContractid.LendingPool, lendingPoolProxy.address); + + const lendingPoolConfiguratorImpl = await deployLendingPoolConfigurator(); + await waitForTx( + await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImpl.address) + ); + const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy( + await addressesProvider.getLendingPoolConfigurator() + ); + await insertContractAddressInDb( + eContractid.LendingPoolConfigurator, + 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( + ALL_ASSETS_INITIAL_PRICES, + { + WETH: mockTokens.WETH.address, + DAI: mockTokens.DAI.address, + TUSD: mockTokens.TUSD.address, + USDC: mockTokens.USDC.address, + USDT: mockTokens.USDT.address, + SUSD: mockTokens.SUSD.address, + AAVE: mockTokens.AAVE.address, + BAT: mockTokens.BAT.address, + MKR: mockTokens.MKR.address, + LINK: mockTokens.LINK.address, + KNC: mockTokens.KNC.address, + WBTC: mockTokens.WBTC.address, + MANA: mockTokens.MANA.address, + ZRX: mockTokens.ZRX.address, + SNX: mockTokens.SNX.address, + BUSD: mockTokens.BUSD.address, + YFI: mockTokens.BUSD.address, + REN: mockTokens.REN.address, + UNI: mockTokens.UNI.address, + ENJ: mockTokens.ENJ.address, + UniDAI: mockTokens.UniDAI.address, + UniUSDC: mockTokens.UniUSDC.address, + UniUSDT: mockTokens.UniUSDT.address, + UniWBTC: mockTokens.UniWBTC.address, + UniWETH: mockTokens.UniWETH.address, + UniDAIWETH: mockTokens.UniDAIWETH.address, + UniWBTCWETH: mockTokens.UniWBTCWETH.address, + UniAAVEWETH: mockTokens.UniAAVEWETH.address, + UniBATWETH: mockTokens.UniBATWETH.address, + UniUSDCDAI: mockTokens.UniUSDCDAI.address, + UniCRVWETH: mockTokens.UniCRVWETH.address, + UniLINKWETH: mockTokens.UniLINKWETH.address, + UniMKRWETH: mockTokens.UniMKRWETH.address, + UniRENWETH: mockTokens.UniRENWETH.address, + UniSNXWETH: mockTokens.UniSNXWETH.address, + UniUNIWETH: mockTokens.UniUNIWETH.address, + UniUSDCWETH: mockTokens.UniUSDCWETH.address, + UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, + UniYFIWETH: mockTokens.UniYFIWETH.address, + USD: USD_ADDRESS, + }, + fallbackOracle + ); + + const mockAggregators = await deployAllMockAggregators(MOCK_CHAINLINK_AGGREGATORS_PRICES); + + const allTokenAddresses = Object.entries(mockTokens).reduce( + (accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, tokenContract]) => ({ + ...accum, + [tokenSymbol]: tokenContract.address, + }), + {} + ); + const allAggregatorsAddresses = Object.entries(mockAggregators).reduce( + (accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, aggregator]) => ({ + ...accum, + [tokenSymbol]: aggregator.address, + }), + {} + ); + + const [tokens, aggregators] = getPairsTokenAggregator(allTokenAddresses, allAggregatorsAddresses); + + await deployAaveOracle([tokens, aggregators, fallbackOracle.address, mockTokens.WETH.address]); + await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address)); + + const lendingRateOracle = await deployLendingRateOracle(); + await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); + + const { USD, ...tokensAddressesWithoutUsd } = allTokenAddresses; + const allReservesAddresses = { + ...tokensAddressesWithoutUsd, + }; + await setInitialMarketRatesInRatesOracleByHelper( + LENDING_RATE_ORACLE_RATES_COMMON, + allReservesAddresses, + lendingRateOracle, + aaveAdmin + ); + + const reservesParams = getReservesConfigByPool(AavePools.uniswap); + + const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address); + + await insertContractAddressInDb(eContractid.AaveProtocolDataProvider, testHelpers.address); + const admin = await deployer.getAddress(); + + console.log('Initialize configuration'); + + const config = loadPoolConfig(ConfigNames.Uniswap); + + const treasuryAddress = await getTreasuryAddress(config); + + await initReservesByHelper( + reservesParams, + allReservesAddresses, + admin, + treasuryAddress, + ZERO_ADDRESS, + false + ); + await configureReservesByHelper(reservesParams, allReservesAddresses, testHelpers, admin); + + const collateralManager = await deployLendingPoolCollateralManager(); + await waitForTx( + await addressesProvider.setLendingPoolCollateralManager(collateralManager.address) + ); + await deployMockFlashLoanReceiver(addressesProvider.address); + + // const mockUniswapRouter = await deployMockUniswapRouter(); + + // const adapterParams: [string, string, string] = [ + // addressesProvider.address, + // mockUniswapRouter.address, + // mockTokens.WETH.address, + // ]; + + // await deployUniswapLiquiditySwapAdapter(adapterParams); + // await deployUniswapRepayAdapter(adapterParams); + // await deployFlashLiquidationAdapter(adapterParams); + + await deployWalletBalancerProvider(); + + await deployWETHGateway([mockTokens.UniWETH.address, lendingPoolAddress]); + + console.timeEnd('setup'); +}; + +before(async () => { + await rawBRE.run('set-DRE'); + const [deployer, secondaryWallet] = await getEthersSigners(); + const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; + + if (MAINNET_FORK) { + await rawBRE.run('uniswap:mainnet'); + } else { + console.log('-> Deploying test environment...'); + await buildTestEnv(deployer, secondaryWallet); + } + + await initializeMakeSuite(); + console.log('\n***************'); + console.log('Setup and snapshot finished'); + console.log('***************\n'); +}); diff --git a/test-suites/test-lp/addresses-provider-registry.spec.ts b/test-suites/test-lp/addresses-provider-registry.spec.ts new file mode 100644 index 00000000..77198278 --- /dev/null +++ b/test-suites/test-lp/addresses-provider-registry.spec.ts @@ -0,0 +1,100 @@ +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { ZERO_ADDRESS } from '../../helpers/constants'; +import { ProtocolErrors } from '../../helpers/types'; + +const { expect } = require('chai'); + +makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => { + it('Checks the addresses provider is added to the registry', async () => { + const { addressesProvider, registry } = testEnv; + + const providers = await registry.getAddressesProvidersList(); + + expect(providers.length).to.be.equal(1, 'Invalid length of the addresses providers list'); + expect(providers[0].toString()).to.be.equal( + addressesProvider.address, + ' Invalid addresses provider added to the list' + ); + }); + + it('tries to register an addresses provider with id 0', async () => { + const { users, registry } = testEnv; + const { LPAPR_INVALID_ADDRESSES_PROVIDER_ID } = ProtocolErrors; + + await expect(registry.registerAddressesProvider(users[2].address, '0')).to.be.revertedWith( + LPAPR_INVALID_ADDRESSES_PROVIDER_ID + ); + }); + + it('Registers a new mock addresses provider', async () => { + const { users, registry } = testEnv; + + //simulating an addresses provider using the users[1] wallet address + await registry.registerAddressesProvider(users[1].address, '2'); + + const providers = await registry.getAddressesProvidersList(); + + expect(providers.length).to.be.equal(2, 'Invalid length of the addresses providers list'); + expect(providers[1].toString()).to.be.equal( + users[1].address, + ' Invalid addresses provider added to the list' + ); + }); + + it('Removes the mock addresses provider', async () => { + const { users, registry, addressesProvider } = testEnv; + + const id = await registry.getAddressesProviderIdByAddress(users[1].address); + + expect(id).to.be.equal('2', 'Invalid isRegistered return value'); + + await registry.unregisterAddressesProvider(users[1].address); + + const providers = await registry.getAddressesProvidersList(); + + expect(providers.length).to.be.equal(2, 'Invalid length of the addresses providers list'); + expect(providers[0].toString()).to.be.equal( + addressesProvider.address, + ' Invalid addresses provider added to the list' + ); + expect(providers[1].toString()).to.be.equal(ZERO_ADDRESS, ' Invalid addresses'); + }); + + it('Tries to remove a unregistered addressesProvider', async () => { + const { LPAPR_PROVIDER_NOT_REGISTERED } = ProtocolErrors; + + const { users, registry } = testEnv; + + await expect(registry.unregisterAddressesProvider(users[2].address)).to.be.revertedWith( + LPAPR_PROVIDER_NOT_REGISTERED + ); + }); + + it('Tries to remove a unregistered addressesProvider', async () => { + const { LPAPR_PROVIDER_NOT_REGISTERED } = ProtocolErrors; + + const { users, registry } = testEnv; + + await expect(registry.unregisterAddressesProvider(users[2].address)).to.be.revertedWith( + LPAPR_PROVIDER_NOT_REGISTERED + ); + }); + + it('Tries to add an already added addressesProvider with a different id. Should overwrite the previous id', async () => { + const { users, registry, addressesProvider } = testEnv; + + await registry.registerAddressesProvider(addressesProvider.address, '2'); + + const providers = await registry.getAddressesProvidersList(); + + const id = await registry.getAddressesProviderIdByAddress(addressesProvider.address); + + expect(providers.length).to.be.equal(2, 'Invalid length of the addresses providers list'); + + expect(providers[0].toString()).to.be.equal( + addressesProvider.address, + ' Invalid addresses provider added to the list' + ); + expect(providers[1].toString()).to.be.equal(ZERO_ADDRESS, ' Invalid addresses'); + }); +}); diff --git a/test-suites/test-lp/atoken-modifiers.spec.ts b/test-suites/test-lp/atoken-modifiers.spec.ts new file mode 100644 index 00000000..f1ae1199 --- /dev/null +++ b/test-suites/test-lp/atoken-modifiers.spec.ts @@ -0,0 +1,35 @@ +import { expect } from 'chai'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors } from '../../helpers/types'; + +makeSuite('AToken: Modifiers', (testEnv: TestEnv) => { + const { CT_CALLER_MUST_BE_LENDING_POOL } = ProtocolErrors; + + it('Tries to invoke mint not being the LendingPool', async () => { + const { deployer, aDai } = testEnv; + await expect(aDai.mint(deployer.address, '1', '1')).to.be.revertedWith( + CT_CALLER_MUST_BE_LENDING_POOL + ); + }); + + it('Tries to invoke burn not being the LendingPool', async () => { + const { deployer, aDai } = testEnv; + await expect(aDai.burn(deployer.address, deployer.address, '1', '1')).to.be.revertedWith( + CT_CALLER_MUST_BE_LENDING_POOL + ); + }); + + it('Tries to invoke transferOnLiquidation not being the LendingPool', async () => { + const { deployer, users, aDai } = testEnv; + await expect( + aDai.transferOnLiquidation(deployer.address, users[0].address, '1') + ).to.be.revertedWith(CT_CALLER_MUST_BE_LENDING_POOL); + }); + + it('Tries to invoke transferUnderlyingTo not being the LendingPool', async () => { + const { deployer, aDai } = testEnv; + await expect(aDai.transferUnderlyingTo(deployer.address, '1')).to.be.revertedWith( + CT_CALLER_MUST_BE_LENDING_POOL + ); + }); +}); diff --git a/test-suites/test-lp/atoken-permit.spec.ts b/test-suites/test-lp/atoken-permit.spec.ts new file mode 100644 index 00000000..24e8b39c --- /dev/null +++ b/test-suites/test-lp/atoken-permit.spec.ts @@ -0,0 +1,312 @@ +import { MAX_UINT_AMOUNT, ZERO_ADDRESS } from '../../helpers/constants'; +import { BUIDLEREVM_CHAINID } from '../../helpers/buidler-constants'; +import { buildPermitParams, getSignatureFromTypedData } from '../../helpers/contracts-helpers'; +import { expect } from 'chai'; +import { ethers } from 'ethers'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { DRE } from '../../helpers/misc-utils'; +import { waitForTx } from '../../helpers/misc-utils'; +import { _TypedDataEncoder } from 'ethers/lib/utils'; + +const { parseEther } = ethers.utils; + +makeSuite('AToken: Permit', (testEnv: TestEnv) => { + it('Checks the domain separator', async () => { + const { aDai } = testEnv; + const separator = await aDai.DOMAIN_SEPARATOR(); + + const domain = { + name: await aDai.name(), + version: '1', + chainId: DRE.network.config.chainId, + verifyingContract: aDai.address, + }; + const domainSeparator = _TypedDataEncoder.hashDomain(domain); + + expect(separator).to.be.equal(domainSeparator, 'Invalid domain separator'); + }); + + it('Get aDAI for tests', async () => { + const { dai, pool, deployer } = testEnv; + + await dai.mint(parseEther('20000')); + await dai.approve(pool.address, parseEther('20000')); + + await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); + }); + + it('Reverts submitting a permit with 0 expiration', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const tokenName = await aDai.name(); + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const expiration = 0; + const nonce = (await aDai._nonces(owner.address)).toNumber(); + const permitAmount = ethers.utils.parseEther('2').toString(); + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + tokenName, + owner.address, + spender.address, + nonce, + permitAmount, + expiration.toFixed() + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( + '0', + 'INVALID_ALLOWANCE_BEFORE_PERMIT' + ); + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await expect( + aDai + .connect(spender.signer) + .permit(owner.address, spender.address, permitAmount, expiration, v, r, s) + ).to.be.revertedWith('INVALID_EXPIRATION'); + + expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( + '0', + 'INVALID_ALLOWANCE_AFTER_PERMIT' + ); + }); + + it('Submits a permit with maximum expiration length', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = (await aDai._nonces(owner.address)).toNumber(); + const permitAmount = parseEther('2').toString(); + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + await aDai.name(), + owner.address, + spender.address, + nonce, + deadline, + permitAmount + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( + '0', + 'INVALID_ALLOWANCE_BEFORE_PERMIT' + ); + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await waitForTx( + await aDai + .connect(spender.signer) + .permit(owner.address, spender.address, permitAmount, deadline, v, r, s) + ); + + expect((await aDai._nonces(owner.address)).toNumber()).to.be.equal(1); + }); + + it('Cancels the previous permit', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = (await aDai._nonces(owner.address)).toNumber(); + const permitAmount = '0'; + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + await aDai.name(), + owner.address, + spender.address, + nonce, + deadline, + permitAmount + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( + ethers.utils.parseEther('2'), + 'INVALID_ALLOWANCE_BEFORE_PERMIT' + ); + + await waitForTx( + await aDai + .connect(spender.signer) + .permit(owner.address, spender.address, permitAmount, deadline, v, r, s) + ); + expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( + permitAmount, + 'INVALID_ALLOWANCE_AFTER_PERMIT' + ); + + expect((await aDai._nonces(owner.address)).toNumber()).to.be.equal(2); + }); + + it('Tries to submit a permit with invalid nonce', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = 1000; + const permitAmount = '0'; + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + await aDai.name(), + owner.address, + spender.address, + nonce, + deadline, + permitAmount + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await expect( + aDai + .connect(spender.signer) + .permit(owner.address, spender.address, permitAmount, deadline, v, r, s) + ).to.be.revertedWith('INVALID_SIGNATURE'); + }); + + it('Tries to submit a permit with invalid expiration (previous to the current block)', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const expiration = '1'; + const nonce = (await aDai._nonces(owner.address)).toNumber(); + const permitAmount = '0'; + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + await aDai.name(), + owner.address, + spender.address, + nonce, + expiration, + permitAmount + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await expect( + aDai + .connect(spender.signer) + .permit(owner.address, spender.address, expiration, permitAmount, v, r, s) + ).to.be.revertedWith('INVALID_EXPIRATION'); + }); + + it('Tries to submit a permit with invalid signature', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + const nonce = (await aDai._nonces(owner.address)).toNumber(); + const permitAmount = '0'; + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + await aDai.name(), + owner.address, + spender.address, + nonce, + deadline, + permitAmount + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await expect( + aDai + .connect(spender.signer) + .permit(owner.address, ZERO_ADDRESS, permitAmount, deadline, v, r, s) + ).to.be.revertedWith('INVALID_SIGNATURE'); + }); + + it('Tries to submit a permit with invalid owner', async () => { + const { aDai, deployer, users } = testEnv; + const owner = deployer; + const spender = users[1]; + + const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; + const expiration = MAX_UINT_AMOUNT; + const nonce = (await aDai._nonces(owner.address)).toNumber(); + const permitAmount = '0'; + const msgParams = buildPermitParams( + chainId, + aDai.address, + '1', + await aDai.name(), + owner.address, + spender.address, + nonce, + expiration, + permitAmount + ); + + const ownerPrivateKey = require('../../test-wallets.js').accounts[0].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + + await expect( + aDai + .connect(spender.signer) + .permit(ZERO_ADDRESS, spender.address, expiration, permitAmount, v, r, s) + ).to.be.revertedWith('INVALID_OWNER'); + }); +}); diff --git a/test-suites/test-lp/atoken-transfer.spec.ts b/test-suites/test-lp/atoken-transfer.spec.ts new file mode 100644 index 00000000..78bbed8c --- /dev/null +++ b/test-suites/test-lp/atoken-transfer.spec.ts @@ -0,0 +1,99 @@ +import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, ZERO_ADDRESS } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { expect } from 'chai'; +import { ethers } from 'ethers'; +import { RateMode, ProtocolErrors } from '../../helpers/types'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { CommonsConfig } from '../../markets/uniswap/commons'; + +const AAVE_REFERRAL = CommonsConfig.ProtocolGlobalParams.AaveReferral; + +makeSuite('AToken: Transfer', (testEnv: TestEnv) => { + const { + INVALID_FROM_BALANCE_AFTER_TRANSFER, + INVALID_TO_BALANCE_AFTER_TRANSFER, + VL_TRANSFER_NOT_ALLOWED, + } = ProtocolErrors; + + it('User 0 deposits 1000 DAI, transfers to user 1', async () => { + const { users, pool, dai, aDai } = testEnv; + + await dai.connect(users[0].signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 1 deposits 1000 DAI + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool + .connect(users[0].signer) + .deposit(dai.address, amountDAItoDeposit, users[0].address, '0'); + + await aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit); + + const name = await aDai.name(); + + expect(name).to.be.equal('Aave interest bearing UniDAI'); + + const fromBalance = await aDai.balanceOf(users[0].address); + const toBalance = await aDai.balanceOf(users[1].address); + + expect(fromBalance.toString()).to.be.equal('0', INVALID_FROM_BALANCE_AFTER_TRANSFER); + expect(toBalance.toString()).to.be.equal( + amountDAItoDeposit.toString(), + INVALID_TO_BALANCE_AFTER_TRANSFER + ); + }); + + 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')); + + await weth.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(users[0].signer) + .deposit(weth.address, ethers.utils.parseEther('1.0'), userAddress, '0'); + await pool + .connect(users[1].signer) + .borrow( + weth.address, + ethers.utils.parseEther('0.1'), + RateMode.Stable, + AAVE_REFERRAL, + 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), + VL_TRANSFER_NOT_ALLOWED + ).to.be.revertedWith(VL_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()); + }); +}); diff --git a/test-suites/test-lp/configurator.spec.ts b/test-suites/test-lp/configurator.spec.ts new file mode 100644 index 00000000..f554e19d --- /dev/null +++ b/test-suites/test-lp/configurator.spec.ts @@ -0,0 +1,386 @@ +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { APPROVAL_AMOUNT_LENDING_POOL, RAY } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { ProtocolErrors } from '../../helpers/types'; +import { strategyWETH } from '../../markets/uniswap/reservesConfigs'; + +const { expect } = require('chai'); + +makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { + const { + CALLER_NOT_POOL_ADMIN, + LPC_RESERVE_LIQUIDITY_NOT_0, + RC_INVALID_LTV, + RC_INVALID_LIQ_THRESHOLD, + RC_INVALID_LIQ_BONUS, + RC_INVALID_DECIMALS, + RC_INVALID_RESERVE_FACTOR, + } = ProtocolErrors; + + 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(RC_INVALID_RESERVE_FACTOR); + }); + + it('Deactivates the ETH reserve', async () => { + const { configurator, weth, helpersContract } = testEnv; + await configurator.deactivateReserve(weth.address); + const { isActive } = await helpersContract.getReserveConfigurationData(weth.address); + expect(isActive).to.be.equal(false); + }); + + it('Rectivates the ETH reserve', async () => { + const { configurator, weth, helpersContract } = testEnv; + await configurator.activateReserve(weth.address); + + const { isActive } = await helpersContract.getReserveConfigurationData(weth.address); + expect(isActive).to.be.equal(true); + }); + + it('Check the onlyAaveAdmin on deactivateReserve ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).deactivateReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Check the onlyAaveAdmin on activateReserve ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).activateReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Freezes the ETH reserve', async () => { + const { configurator, weth, helpersContract } = testEnv; + + await configurator.freezeReserve(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(true); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Unfreezes the ETH reserve', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.unfreezeReserve(weth.address); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Check the onlyAaveAdmin on freezeReserve ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).freezeReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Check the onlyAaveAdmin on unfreezeReserve ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).unfreezeReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Deactivates the ETH reserve for borrowing', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.disableBorrowingOnReserve(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(false); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Activates the ETH reserve for borrowing', async () => { + const { configurator, weth, helpersContract } = testEnv; + await configurator.enableBorrowingOnReserve(weth.address, true); + const { variableBorrowIndex } = await helpersContract.getReserveData(weth.address); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(true/*strategyWETH.stableBorrowRateEnabled*/); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + + expect(variableBorrowIndex.toString()).to.be.equal(RAY); + }); + + it('Check the onlyAaveAdmin on disableBorrowingOnReserve ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).disableBorrowingOnReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, true), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Deactivates the ETH reserve as collateral', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.configureReserveAsCollateral(weth.address, 0, 0, 0); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(18); + expect(ltv).to.be.equal(0); + expect(liquidationThreshold).to.be.equal(0); + expect(liquidationBonus).to.be.equal(0); + expect(stableBorrowRateEnabled).to.be.equal(true); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Activates the ETH reserve as collateral', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.configureReserveAsCollateral(weth.address, '8000', '8250', '10500'); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(true/*strategyWETH.stableBorrowRateEnabled*/); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Check the onlyAaveAdmin on configureReserveAsCollateral ', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator + .connect(users[2].signer) + .configureReserveAsCollateral(weth.address, '7500', '8000', '10500'), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Disable stable borrow rate on the ETH reserve', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.disableReserveStableRate(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(false); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Enables stable borrow rate on the ETH reserve', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.enableReserveStableRate(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(true); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + + it('Check the onlyAaveAdmin on disableReserveStableRate', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).disableReserveStableRate(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Check the onlyAaveAdmin on enableReserveStableRate', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).enableReserveStableRate(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Changes the reserve factor of WETH', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.setReserveFactor(weth.address, '1000'); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(1000); + }); + + it('Check the onlyLendingPoolManager on setReserveFactor', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).setReserveFactor(weth.address, '2000'), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Reverts when trying to disable the DAI reserve with liquidity on it', async () => { + const { dai, pool, configurator } = testEnv; + const userAddress = await pool.signer.getAddress(); + await dai.mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access depositor wallet + await dai.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + //user 1 deposits 1000 DAI + await pool.deposit(dai.address, amountDAItoDeposit, userAddress, '0'); + + await expect( + configurator.deactivateReserve(dai.address), + LPC_RESERVE_LIQUIDITY_NOT_0 + ).to.be.revertedWith(LPC_RESERVE_LIQUIDITY_NOT_0); + }); +}); diff --git a/test-suites/test-lp/delegation-aware-atoken.spec.ts b/test-suites/test-lp/delegation-aware-atoken.spec.ts new file mode 100644 index 00000000..ba11ed7f --- /dev/null +++ b/test-suites/test-lp/delegation-aware-atoken.spec.ts @@ -0,0 +1,64 @@ +import { MAX_UINT_AMOUNT, ZERO_ADDRESS } from '../../helpers/constants'; +import { BUIDLEREVM_CHAINID } from '../../helpers/buidler-constants'; +import { buildPermitParams, getSignatureFromTypedData } from '../../helpers/contracts-helpers'; +import { expect } from 'chai'; +import { ethers } from 'ethers'; +import { eEthereumNetwork, ProtocolErrors } from '../../helpers/types'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { DRE } from '../../helpers/misc-utils'; +import { + ConfigNames, + getATokenDomainSeparatorPerNetwork, + getTreasuryAddress, + loadPoolConfig, +} from '../../helpers/configuration'; +import { waitForTx } from '../../helpers/misc-utils'; +import { + deployDelegationAwareAToken, + deployMintableDelegationERC20, +} from '../../helpers/contracts-deployments'; +import { DelegationAwareATokenFactory } from '../../types'; +import { DelegationAwareAToken } from '../../types/DelegationAwareAToken'; +import { MintableDelegationERC20 } from '../../types/MintableDelegationERC20'; +import UniswapConfig from '../../markets/uniswap'; + +const { parseEther } = ethers.utils; + +makeSuite('AToken: underlying delegation', (testEnv: TestEnv) => { + const poolConfig = loadPoolConfig(ConfigNames.Commons); + let delegationAToken = {}; + let delegationERC20 = {}; + + it('Deploys a new MintableDelegationERC20 and a DelegationAwareAToken', async () => { + const { pool } = testEnv; + + delegationERC20 = await deployMintableDelegationERC20(['DEL', 'DEL', '18']); + + delegationAToken = await deployDelegationAwareAToken( + [pool.address, delegationERC20.address, await getTreasuryAddress(UniswapConfig), ZERO_ADDRESS, 'aDEL', 'aDEL'], + false + ); + + //await delegationAToken.initialize(pool.address, ZERO_ADDRESS, delegationERC20.address, ZERO_ADDRESS, '18', 'aDEL', 'aDEL'); + + console.log((await delegationAToken.decimals()).toString()); + }); + + it('Tries to delegate with the caller not being the Aave admin', async () => { + const { users } = testEnv; + + await expect( + delegationAToken.connect(users[1].signer).delegateUnderlyingTo(users[2].address) + ).to.be.revertedWith(ProtocolErrors.CALLER_NOT_POOL_ADMIN); + }); + + it('Tries to delegate to user 2', async () => { + const { users } = testEnv; + + await delegationAToken.delegateUnderlyingTo(users[2].address); + + const delegateeAddress = await delegationERC20.delegatee(); + + expect(delegateeAddress).to.be.equal(users[2].address); + }); +}); diff --git a/test-suites/test-lp/flashloan.spec.ts b/test-suites/test-lp/flashloan.spec.ts new file mode 100644 index 00000000..4a5f5576 --- /dev/null +++ b/test-suites/test-lp/flashloan.spec.ts @@ -0,0 +1,497 @@ +import BigNumber from 'bignumber.js'; + +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { APPROVAL_AMOUNT_LENDING_POOL, oneRay } from '../../helpers/constants'; +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, + getStableDebtToken, + getVariableDebtToken, +} from '../../helpers/contracts-getters'; + +const { expect } = require('chai'); + +makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { + let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver; + const { + VL_COLLATERAL_BALANCE_IS_0, + TRANSFER_AMOUNT_EXCEEDS_BALANCE, + LP_INVALID_FLASHLOAN_MODE, + SAFEERC20_LOWLEVEL_CALL, + LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN, + LP_BORROW_ALLOWANCE_NOT_ENOUGH, + } = ProtocolErrors; + + before(async () => { + _mockFlashLoanReceiver = await getMockFlashLoanReceiver(); + }); + + it('Deposits WETH into the reserve', async () => { + const { pool, weth } = testEnv; + const userAddress = await pool.signer.getAddress(); + const amountToDeposit = ethers.utils.parseEther('1'); + + await weth.mint(amountToDeposit); + + await weth.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool.deposit(weth.address, amountToDeposit, userAddress, '0'); + }); + + it('Takes WETH flashloan with mode = 0, returns the funds correctly', async () => { + const { pool, helpersContract, weth } = testEnv; + + await pool.flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [ethers.utils.parseEther('0.8')], + [0], + _mockFlashLoanReceiver.address, + '0x10', + '0' + ); + + ethers.utils.parseUnits('10000'); + + const reserveData = await helpersContract.getReserveData(weth.address); + + const currentLiquidityRate = reserveData.liquidityRate; + const currentLiquidityIndex = reserveData.liquidityIndex; + + const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) + .plus(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()); + + expect(totalLiquidity.toString()).to.be.equal('1000720000000000000'); + expect(currentLiquidityRate.toString()).to.be.equal('0'); + expect(currentLiquidityIndex.toString()).to.be.equal('1000720000000000000000000000'); + }); + + it('Takes an ETH flashloan with mode = 0 as big as the available liquidity', async () => { + const { pool, helpersContract, weth } = testEnv; + + const reserveDataBefore = await helpersContract.getReserveData(weth.address); + const txResult = await pool.flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + ['1000720000000000000'], + [0], + _mockFlashLoanReceiver.address, + '0x10', + '0' + ); + + const reserveData = await helpersContract.getReserveData(weth.address); + + const currentLiqudityRate = reserveData.liquidityRate; + const currentLiquidityIndex = reserveData.liquidityIndex; + + const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) + .plus(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()); + + expect(totalLiquidity.toString()).to.be.equal('1001620648000000000'); + expect(currentLiqudityRate.toString()).to.be.equal('0'); + expect(currentLiquidityIndex.toString()).to.be.equal('1001620648000000000000000000'); + }); + + it('Takes WETH flashloan, does not return the funds with mode = 0. (revert expected)', async () => { + const { pool, weth, users } = testEnv; + const caller = users[1]; + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [ethers.utils.parseEther('0.8')], + [0], + caller.address, + '0x10', + '0' + ) + ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); + }); + + it('Takes WETH flashloan, simulating a receiver as EOA (revert expected)', async () => { + const { pool, weth, users } = testEnv; + const caller = users[1]; + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + await _mockFlashLoanReceiver.setSimulateEOA(true); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [ethers.utils.parseEther('0.8')], + [0], + caller.address, + '0x10', + '0' + ) + ).to.be.revertedWith(LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN); + }); + + it('Takes a WETH flashloan with an invalid mode. (revert expected)', async () => { + const { pool, weth, users } = testEnv; + const caller = users[1]; + await _mockFlashLoanReceiver.setSimulateEOA(false); + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [ethers.utils.parseEther('0.8')], + [4], + caller.address, + '0x10', + '0' + ) + ).to.be.reverted; + }); + + it('Caller deposits 1000 DAI as collateral, Takes WETH flashloan with mode = 2, does not return the funds. A variable loan for caller is created', async () => { + const { dai, pool, weth, users, helpersContract } = testEnv; + + const caller = users[1]; + + await dai.connect(caller.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + await dai.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const amountToDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool.connect(caller.signer).deposit(dai.address, amountToDeposit, caller.address, '0'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + await pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [ethers.utils.parseEther('0.8')], + [2], + caller.address, + '0x10', + '0' + ); + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const wethDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + const callerDebt = await wethDebtToken.balanceOf(caller.address); + + expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt'); + }); + + it('tries to take a flashloan that is bigger than the available liquidity (revert expected)', async () => { + const { pool, weth, users } = testEnv; + const caller = users[1]; + + await expect( + pool.connect(caller.signer).flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + ['1004415000000000000'], //slightly higher than the available liquidity + [2], + caller.address, + '0x10', + '0' + ), + TRANSFER_AMOUNT_EXCEEDS_BALANCE + ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); + }); + + it('tries to take a flashloan using a non contract address as receiver (revert expected)', async () => { + const { pool, deployer, weth, users } = testEnv; + const caller = users[1]; + + await expect( + pool.flashLoan( + deployer.address, + [weth.address], + ['1000000000000000000'], + [2], + caller.address, + '0x10', + '0' + ) + ).to.be.reverted; + }); + + it('Deposits USDC into the reserve', async () => { + const { usdc, pool } = testEnv; + const userAddress = await pool.signer.getAddress(); + + await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + await usdc.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const amountToDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); + + await pool.deposit(usdc.address, amountToDeposit, userAddress, '0'); + }); + + it('Takes out a 500 USDC flashloan, returns the funds correctly', async () => { + const { usdc, pool, helpersContract, deployer: depositor } = testEnv; + + await _mockFlashLoanReceiver.setFailExecutionTransfer(false); + + const reserveDataBefore = await helpersContract.getReserveData(usdc.address); + + const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); + + await pool.flashLoan( + _mockFlashLoanReceiver.address, + [usdc.address], + [flashloanAmount], + [0], + _mockFlashLoanReceiver.address, + '0x10', + '0' + ); + + const reserveDataAfter = helpersContract.getReserveData(usdc.address); + + const reserveData = await helpersContract.getReserveData(usdc.address); + const userData = await helpersContract.getUserReserveData(usdc.address, depositor.address); + + const totalLiquidity = reserveData.availableLiquidity + .add(reserveData.totalStableDebt) + .add(reserveData.totalVariableDebt) + .toString(); + const currentLiqudityRate = reserveData.liquidityRate.toString(); + const currentLiquidityIndex = reserveData.liquidityIndex.toString(); + const currentUserBalance = userData.currentATokenBalance.toString(); + + const expectedLiquidity = await convertToCurrencyDecimals(usdc.address, '1000.450'); + + expect(totalLiquidity).to.be.equal(expectedLiquidity, 'Invalid total liquidity'); + expect(currentLiqudityRate).to.be.equal('0', 'Invalid liquidity rate'); + expect(currentLiquidityIndex).to.be.equal( + new BigNumber('1.00045').multipliedBy(oneRay).toFixed(), + 'Invalid liquidity index' + ); + expect(currentUserBalance.toString()).to.be.equal(expectedLiquidity, 'Invalid user balance'); + }); + + it('Takes out a 500 USDC flashloan with mode = 0, does not return the funds. (revert expected)', async () => { + const { usdc, pool, users } = testEnv; + const caller = users[2]; + + const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [usdc.address], + [flashloanAmount], + [2], + caller.address, + '0x10', + '0' + ) + ).to.be.revertedWith(VL_COLLATERAL_BALANCE_IS_0); + }); + + it('Caller deposits 5 WETH as collateral, Takes a USDC flashloan with mode = 2, does not return the funds. A loan for caller is created', async () => { + const { usdc, pool, weth, users, helpersContract } = testEnv; + + const caller = users[2]; + + await weth.connect(caller.signer).mint(await convertToCurrencyDecimals(weth.address, '5')); + + await weth.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const amountToDeposit = await convertToCurrencyDecimals(weth.address, '5'); + + await pool.connect(caller.signer).deposit(weth.address, amountToDeposit, caller.address, '0'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); + + await pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [usdc.address], + [flashloanAmount], + [2], + caller.address, + '0x10', + '0' + ); + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + usdc.address + ); + + const usdcDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + const callerDebt = await usdcDebtToken.balanceOf(caller.address); + + expect(callerDebt.toString()).to.be.equal('500000000', 'Invalid user debt'); + }); + + it('Caller deposits 1000 DAI as collateral, Takes a WETH flashloan with mode = 0, does not approve the transfer of the funds', async () => { + const { dai, pool, weth, users } = testEnv; + const caller = users[3]; + + await dai.connect(caller.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + await dai.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const amountToDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool.connect(caller.signer).deposit(dai.address, amountToDeposit, caller.address, '0'); + + const flashAmount = ethers.utils.parseEther('0.8'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(false); + await _mockFlashLoanReceiver.setAmountToApprove(flashAmount.div(2)); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [flashAmount], + [0], + caller.address, + '0x10', + '0' + ) + ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); + }); + + it('Caller takes a WETH flashloan with mode = 1', async () => { + const { dai, pool, weth, users, helpersContract } = testEnv; + + const caller = users[3]; + + const flashAmount = ethers.utils.parseEther('0.8'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + await pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [flashAmount], + [1], + caller.address, + '0x10', + '0' + ); + + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const wethDebtToken = await getStableDebtToken(stableDebtTokenAddress); + + const callerDebt = await wethDebtToken.balanceOf(caller.address); + + 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(LP_BORROW_ALLOWANCE_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'); + + const reserveData = await pool.getReserveData(weth.address); + + const stableDebtToken = await getVariableDebtToken(reserveData.stableDebtTokenAddress); + + // Deposited for onBehalfOf user already, delegate borrow allowance + await stableDebtToken.connect(onBehalfOf.signer).approveDelegation(caller.address, 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 getStableDebtToken(stableDebtTokenAddress); + + const onBehalfOfDebt = await wethDebtToken.balanceOf(onBehalfOf.address); + + expect(onBehalfOfDebt.toString()).to.be.equal( + '800000000000000000', + 'Invalid onBehalfOf user debt' + ); + }); +}); diff --git a/test-suites/test-lp/helpers/actions.ts b/test-suites/test-lp/helpers/actions.ts new file mode 100644 index 00000000..62f9f8e3 --- /dev/null +++ b/test-suites/test-lp/helpers/actions.ts @@ -0,0 +1,770 @@ +import BigNumber from 'bignumber.js'; + +import { + calcExpectedReserveDataAfterBorrow, + calcExpectedReserveDataAfterDeposit, + calcExpectedReserveDataAfterRepay, + calcExpectedReserveDataAfterStableRateRebalance, + calcExpectedReserveDataAfterSwapRateMode, + calcExpectedReserveDataAfterWithdraw, + calcExpectedUserDataAfterBorrow, + calcExpectedUserDataAfterDeposit, + calcExpectedUserDataAfterRepay, + calcExpectedUserDataAfterSetUseAsCollateral, + calcExpectedUserDataAfterStableRateRebalance, + calcExpectedUserDataAfterSwapRateMode, + calcExpectedUserDataAfterWithdraw, +} from './utils/calculations'; +import { getReserveAddressFromSymbol, getReserveData, getUserData } from './utils/helpers'; + +import { convertToCurrencyDecimals } from '../../../helpers/contracts-helpers'; +import { + getAToken, + getMintableERC20, + getStableDebtToken, + getVariableDebtToken, +} from '../../../helpers/contracts-getters'; +import { MAX_UINT_AMOUNT, ONE_YEAR } from '../../../helpers/constants'; +import { SignerWithAddress, TestEnv } from './make-suite'; +import { advanceTimeAndBlock, DRE, timeLatest, waitForTx } from '../../../helpers/misc-utils'; + +import chai from 'chai'; +import { ReserveData, UserReserveData } from './utils/interfaces'; +import { ContractReceipt } from 'ethers'; +import { AToken } from '../../../types/AToken'; +import { RateMode, tEthereumAddress } from '../../../helpers/types'; + +const { expect } = chai; + +const almostEqualOrEqual = function ( + this: any, + expected: ReserveData | UserReserveData, + actual: ReserveData | UserReserveData +) { + const keys = Object.keys(actual); + + keys.forEach((key) => { + if ( + key === 'lastUpdateTimestamp' || + key === 'marketStableRate' || + key === 'symbol' || + key === 'aTokenAddress' || + key === 'decimals' || + key === 'totalStableDebtLastUpdated' + ) { + // skipping consistency check on accessory data + return; + } + + this.assert(actual[key] != undefined, `Property ${key} is undefined in the actual data`); + expect(expected[key] != undefined, `Property ${key} is undefined in the expected data`); + + if (expected[key] == null || actual[key] == null) { + console.log('Found a undefined value for Key ', key, ' value ', expected[key], actual[key]); + } + + if (actual[key] instanceof BigNumber) { + const actualValue = (actual[key]).decimalPlaces(0, BigNumber.ROUND_DOWN); + const expectedValue = (expected[key]).decimalPlaces(0, BigNumber.ROUND_DOWN); + + this.assert( + actualValue.eq(expectedValue) || + actualValue.plus(1).eq(expectedValue) || + actualValue.eq(expectedValue.plus(1)) || + actualValue.plus(2).eq(expectedValue) || + actualValue.eq(expectedValue.plus(2)) || + actualValue.plus(3).eq(expectedValue) || + actualValue.eq(expectedValue.plus(3)), + `expected #{act} to be almost equal or equal #{exp} for property ${key}`, + `expected #{act} to be almost equal or equal #{exp} for property ${key}`, + expectedValue.toFixed(0), + actualValue.toFixed(0) + ); + } else { + this.assert( + actual[key] !== null && + expected[key] !== null && + actual[key].toString() === expected[key].toString(), + `expected #{act} to be equal #{exp} for property ${key}`, + `expected #{act} to be equal #{exp} for property ${key}`, + expected[key], + actual[key] + ); + } + }); +}; + +chai.use(function (chai: any, utils: any) { + chai.Assertion.overwriteMethod('almostEqualOrEqual', function (original: any) { + return function (this: any, expected: ReserveData | UserReserveData) { + const actual = (expected as ReserveData) + ? this._obj + : this._obj; + + almostEqualOrEqual.apply(this, [expected, actual]); + }; + }); +}); + +interface ActionsConfig { + skipIntegrityCheck: boolean; +} + +export const configuration: ActionsConfig = {}; + +export const mint = async (reserveSymbol: string, amount: string, user: SignerWithAddress) => { + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const token = await getMintableERC20(reserve); + + await waitForTx( + await token.connect(user.signer).mint(await convertToCurrencyDecimals(reserve, amount)) + ); +}; + +export const approve = async (reserveSymbol: string, user: SignerWithAddress, testEnv: TestEnv) => { + const { pool } = testEnv; + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const token = await getMintableERC20(reserve); + + await waitForTx( + await token.connect(user.signer).approve(pool.address, '100000000000000000000000000000') + ); +}; + +export const deposit = async ( + reserveSymbol: string, + amount: string, + sender: SignerWithAddress, + onBehalfOf: tEthereumAddress, + sendValue: string, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const amountToDeposit = await convertToCurrencyDecimals(reserve, amount); + + const txOptions: any = {}; + + const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( + reserve, + onBehalfOf, + testEnv, + sender.address + ); + + if (sendValue) { + txOptions.value = await convertToCurrencyDecimals(reserve, sendValue); + } + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool + .connect(sender.signer) + .deposit(reserve, amountToDeposit, onBehalfOf, '0', txOptions) + ); + + const { + reserveData: reserveDataAfter, + userData: userDataAfter, + timestamp, + } = await getContractsData(reserve, onBehalfOf, testEnv, sender.address); + + const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); + + const expectedReserveData = calcExpectedReserveDataAfterDeposit( + amountToDeposit.toString(), + reserveDataBefore, + txTimestamp + ); + + const expectedUserReserveData = calcExpectedUserDataAfterDeposit( + amountToDeposit.toString(), + reserveDataBefore, + expectedReserveData, + userDataBefore, + txTimestamp, + timestamp, + txCost + ); + + expectEqual(reserveDataAfter, expectedReserveData); + expectEqual(userDataAfter, expectedUserReserveData); + + // truffleAssert.eventEmitted(txResult, "Deposit", (ev: any) => { + // const {_reserve, _user, _amount} = ev; + // return ( + // _reserve === reserve && + // _user === user && + // new BigNumber(_amount).isEqualTo(new BigNumber(amountToDeposit)) + // ); + // }); + } else if (expectedResult === 'revert') { + await expect( + pool.connect(sender.signer).deposit(reserve, amountToDeposit, onBehalfOf, '0', txOptions), + revertMessage + ).to.be.reverted; + } +}; + +export const withdraw = async ( + reserveSymbol: string, + amount: string, + user: SignerWithAddress, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const { + aTokenInstance, + reserve, + userData: userDataBefore, + reserveData: reserveDataBefore, + } = await getDataBeforeAction(reserveSymbol, user.address, testEnv); + + let amountToWithdraw = '0'; + + if (amount !== '-1') { + amountToWithdraw = (await convertToCurrencyDecimals(reserve, amount)).toString(); + } else { + amountToWithdraw = MAX_UINT_AMOUNT; + } + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool.connect(user.signer).withdraw(reserve, amountToWithdraw, user.address) + ); + + const { + reserveData: reserveDataAfter, + userData: userDataAfter, + timestamp, + } = await getContractsData(reserve, user.address, testEnv); + + const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); + + const expectedReserveData = calcExpectedReserveDataAfterWithdraw( + amountToWithdraw, + reserveDataBefore, + userDataBefore, + txTimestamp + ); + + const expectedUserData = calcExpectedUserDataAfterWithdraw( + amountToWithdraw, + reserveDataBefore, + expectedReserveData, + userDataBefore, + txTimestamp, + timestamp, + txCost + ); + + expectEqual(reserveDataAfter, expectedReserveData); + expectEqual(userDataAfter, expectedUserData); + + // truffleAssert.eventEmitted(txResult, "Redeem", (ev: any) => { + // const {_from, _value} = ev; + // return ( + // _from === user && new BigNumber(_value).isEqualTo(actualAmountRedeemed) + // ); + // }); + } else if (expectedResult === 'revert') { + await expect( + pool.connect(user.signer).withdraw(reserve, amountToWithdraw, user.address), + revertMessage + ).to.be.reverted; + } +}; + +export const delegateBorrowAllowance = async ( + reserve: string, + amount: string, + interestRateMode: string, + user: SignerWithAddress, + receiver: tEthereumAddress, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const reserveAddress: tEthereumAddress = await getReserveAddressFromSymbol(reserve); + + const amountToDelegate: string = await ( + await convertToCurrencyDecimals(reserveAddress, amount) + ).toString(); + + const reserveData = await pool.getReserveData(reserveAddress); + + const debtToken = + interestRateMode === '1' + ? await getStableDebtToken(reserveData.stableDebtTokenAddress) + : await getVariableDebtToken(reserveData.variableDebtTokenAddress); + + const delegateAllowancePromise = debtToken + .connect(user.signer) + .approveDelegation(receiver, amountToDelegate); + + if (expectedResult === 'revert' && revertMessage) { + await expect(delegateAllowancePromise, revertMessage).to.be.revertedWith(revertMessage); + return; + } else { + await waitForTx(await delegateAllowancePromise); + const allowance = await debtToken.borrowAllowance(user.address, receiver); + expect(allowance.toString()).to.be.equal( + amountToDelegate, + 'borrowAllowance is set incorrectly' + ); + } +}; + +export const borrow = async ( + reserveSymbol: string, + amount: string, + interestRateMode: string, + user: SignerWithAddress, + onBehalfOf: tEthereumAddress, + timeTravel: string, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( + reserve, + onBehalfOf, + testEnv, + user.address + ); + + const amountToBorrow = await convertToCurrencyDecimals(reserve, amount); + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool + .connect(user.signer) + .borrow(reserve, amountToBorrow, interestRateMode, '0', onBehalfOf) + ); + + const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); + + if (timeTravel) { + const secondsToTravel = new BigNumber(timeTravel).multipliedBy(ONE_YEAR).div(365).toNumber(); + + await advanceTimeAndBlock(secondsToTravel); + } + + const { + reserveData: reserveDataAfter, + userData: userDataAfter, + timestamp, + } = await getContractsData(reserve, onBehalfOf, testEnv, user.address); + + const expectedReserveData = calcExpectedReserveDataAfterBorrow( + amountToBorrow.toString(), + interestRateMode, + reserveDataBefore, + userDataBefore, + txTimestamp, + timestamp + ); + + const expectedUserData = calcExpectedUserDataAfterBorrow( + amountToBorrow.toString(), + interestRateMode, + reserveDataBefore, + expectedReserveData, + userDataBefore, + txTimestamp, + timestamp + ); + + expectEqual(reserveDataAfter, expectedReserveData); + expectEqual(userDataAfter, expectedUserData); + + // truffleAssert.eventEmitted(txResult, "Borrow", (ev: any) => { + // const { + // _reserve, + // _user, + // _amount, + // _borrowRateMode, + // _borrowRate, + // _originationFee, + // } = ev; + // return ( + // _reserve.toLowerCase() === reserve.toLowerCase() && + // _user.toLowerCase() === user.toLowerCase() && + // new BigNumber(_amount).eq(amountToBorrow) && + // new BigNumber(_borrowRateMode).eq(expectedUserData.borrowRateMode) && + // new BigNumber(_borrowRate).eq(expectedUserData.borrowRate) && + // new BigNumber(_originationFee).eq( + // expectedUserData.originationFee.minus(userDataBefore.originationFee) + // ) + // ); + // }); + } else if (expectedResult === 'revert') { + await expect( + pool.connect(user.signer).borrow(reserve, amountToBorrow, interestRateMode, '0', onBehalfOf), + revertMessage + ).to.be.reverted; + } +}; + +export const repay = async ( + reserveSymbol: string, + amount: string, + rateMode: string, + user: SignerWithAddress, + onBehalfOf: SignerWithAddress, + sendValue: string, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( + reserve, + onBehalfOf.address, + testEnv + ); + + let amountToRepay = '0'; + + if (amount !== '-1') { + amountToRepay = (await convertToCurrencyDecimals(reserve, amount)).toString(); + } else { + amountToRepay = MAX_UINT_AMOUNT; + } + amountToRepay = '0x' + new BigNumber(amountToRepay).toString(16); + + const txOptions: any = {}; + + if (sendValue) { + const valueToSend = await convertToCurrencyDecimals(reserve, sendValue); + txOptions.value = '0x' + new BigNumber(valueToSend.toString()).toString(16); + } + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool + .connect(user.signer) + .repay(reserve, amountToRepay, rateMode, onBehalfOf.address, txOptions) + ); + + const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); + + const { + reserveData: reserveDataAfter, + userData: userDataAfter, + timestamp, + } = await getContractsData(reserve, onBehalfOf.address, testEnv); + + const expectedReserveData = calcExpectedReserveDataAfterRepay( + amountToRepay, + rateMode, + reserveDataBefore, + userDataBefore, + txTimestamp, + timestamp + ); + + const expectedUserData = calcExpectedUserDataAfterRepay( + amountToRepay, + rateMode, + reserveDataBefore, + expectedReserveData, + userDataBefore, + user.address, + onBehalfOf.address, + txTimestamp, + timestamp + ); + + expectEqual(reserveDataAfter, expectedReserveData); + expectEqual(userDataAfter, expectedUserData); + + // truffleAssert.eventEmitted(txResult, "Repay", (ev: any) => { + // const {_reserve, _user, _repayer} = ev; + + // return ( + // _reserve.toLowerCase() === reserve.toLowerCase() && + // _user.toLowerCase() === onBehalfOf.toLowerCase() && + // _repayer.toLowerCase() === user.toLowerCase() + // ); + // }); + } else if (expectedResult === 'revert') { + await expect( + pool + .connect(user.signer) + .repay(reserve, amountToRepay, rateMode, onBehalfOf.address, txOptions), + revertMessage + ).to.be.reverted; + } +}; + +export const setUseAsCollateral = async ( + reserveSymbol: string, + user: SignerWithAddress, + useAsCollateral: string, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( + reserve, + user.address, + testEnv + ); + + const useAsCollateralBool = useAsCollateral.toLowerCase() === 'true'; + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool.connect(user.signer).setUserUseReserveAsCollateral(reserve, useAsCollateralBool) + ); + + const { txCost } = await getTxCostAndTimestamp(txResult); + + const { userData: userDataAfter } = await getContractsData(reserve, user.address, testEnv); + + const expectedUserData = calcExpectedUserDataAfterSetUseAsCollateral( + useAsCollateral.toLocaleLowerCase() === 'true', + reserveDataBefore, + userDataBefore, + txCost + ); + + expectEqual(userDataAfter, expectedUserData); + // if (useAsCollateralBool) { + // truffleAssert.eventEmitted(txResult, 'ReserveUsedAsCollateralEnabled', (ev: any) => { + // const {_reserve, _user} = ev; + // return _reserve === reserve && _user === user; + // }); + // } else { + // truffleAssert.eventEmitted(txResult, 'ReserveUsedAsCollateralDisabled', (ev: any) => { + // const {_reserve, _user} = ev; + // return _reserve === reserve && _user === user; + // }); + // } + } else if (expectedResult === 'revert') { + await expect( + pool.connect(user.signer).setUserUseReserveAsCollateral(reserve, useAsCollateralBool), + revertMessage + ).to.be.reverted; + } +}; + +export const swapBorrowRateMode = async ( + reserveSymbol: string, + user: SignerWithAddress, + rateMode: string, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( + reserve, + user.address, + testEnv + ); + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool.connect(user.signer).swapBorrowRateMode(reserve, rateMode) + ); + + const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); + + const { reserveData: reserveDataAfter, userData: userDataAfter } = await getContractsData( + reserve, + user.address, + testEnv + ); + + const expectedReserveData = calcExpectedReserveDataAfterSwapRateMode( + reserveDataBefore, + userDataBefore, + rateMode, + txTimestamp + ); + + const expectedUserData = calcExpectedUserDataAfterSwapRateMode( + reserveDataBefore, + expectedReserveData, + userDataBefore, + rateMode, + txCost, + txTimestamp + ); + + expectEqual(reserveDataAfter, expectedReserveData); + expectEqual(userDataAfter, expectedUserData); + + // truffleAssert.eventEmitted(txResult, "Swap", (ev: any) => { + // const {_user, _reserve, _newRateMode, _newRate} = ev; + // return ( + // _user === user && + // _reserve == reserve && + // new BigNumber(_newRateMode).eq(expectedUserData.borrowRateMode) && + // new BigNumber(_newRate).eq(expectedUserData.borrowRate) + // ); + // }); + } else if (expectedResult === 'revert') { + await expect(pool.connect(user.signer).swapBorrowRateMode(reserve, rateMode), revertMessage).to + .be.reverted; + } +}; + +export const rebalanceStableBorrowRate = async ( + reserveSymbol: string, + user: SignerWithAddress, + target: SignerWithAddress, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const { pool } = testEnv; + + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( + reserve, + target.address, + testEnv + ); + + if (expectedResult === 'success') { + const txResult = await waitForTx( + await pool.connect(user.signer).rebalanceStableBorrowRate(reserve, target.address) + ); + + const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); + + const { reserveData: reserveDataAfter, userData: userDataAfter } = await getContractsData( + reserve, + target.address, + testEnv + ); + + const expectedReserveData = calcExpectedReserveDataAfterStableRateRebalance( + reserveDataBefore, + userDataBefore, + txTimestamp + ); + + const expectedUserData = calcExpectedUserDataAfterStableRateRebalance( + reserveDataBefore, + expectedReserveData, + userDataBefore, + txCost, + txTimestamp + ); + + expectEqual(reserveDataAfter, expectedReserveData); + expectEqual(userDataAfter, expectedUserData); + + // truffleAssert.eventEmitted(txResult, 'RebalanceStableBorrowRate', (ev: any) => { + // const {_user, _reserve, _newStableRate} = ev; + // return ( + // _user.toLowerCase() === target.toLowerCase() && + // _reserve.toLowerCase() === reserve.toLowerCase() && + // new BigNumber(_newStableRate).eq(expectedUserData.borrowRate) + // ); + // }); + } else if (expectedResult === 'revert') { + await expect( + pool.connect(user.signer).rebalanceStableBorrowRate(reserve, target.address), + revertMessage + ).to.be.reverted; + } +}; + +const expectEqual = ( + actual: UserReserveData | ReserveData, + expected: UserReserveData | ReserveData +) => { + if (!configuration.skipIntegrityCheck) { + // @ts-ignore + expect(actual).to.be.almostEqualOrEqual(expected); + } +}; + +interface ActionData { + reserve: string; + reserveData: ReserveData; + userData: UserReserveData; + aTokenInstance: AToken; +} + +const getDataBeforeAction = async ( + reserveSymbol: string, + user: tEthereumAddress, + testEnv: TestEnv +): Promise => { + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + + const { reserveData, userData } = await getContractsData(reserve, user, testEnv); + const aTokenInstance = await getAToken(reserveData.aTokenAddress); + return { + reserve, + reserveData, + userData, + aTokenInstance, + }; +}; + +export const getTxCostAndTimestamp = async (tx: ContractReceipt) => { + if (!tx.blockNumber || !tx.transactionHash || !tx.cumulativeGasUsed) { + throw new Error('No tx blocknumber'); + } + const txTimestamp = new BigNumber((await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp); + + const txInfo = await DRE.ethers.provider.getTransaction(tx.transactionHash); + const txCost = new BigNumber(tx.cumulativeGasUsed.toString()).multipliedBy( + txInfo.gasPrice.toString() + ); + + return { txCost, txTimestamp }; +}; + +export const getContractsData = async ( + reserve: string, + user: string, + testEnv: TestEnv, + sender?: string +) => { + const { pool, helpersContract } = testEnv; + + const [userData, reserveData, timestamp] = await Promise.all([ + getUserData(pool, helpersContract, reserve, user, sender || user), + getReserveData(helpersContract, reserve), + timeLatest(), + ]); + + return { + reserveData, + userData, + timestamp: new BigNumber(timestamp), + }; +}; diff --git a/test-suites/test-lp/helpers/almost-equal.ts b/test-suites/test-lp/helpers/almost-equal.ts new file mode 100644 index 00000000..e0017056 --- /dev/null +++ b/test-suites/test-lp/helpers/almost-equal.ts @@ -0,0 +1,31 @@ +import BigNumber from 'bignumber.js'; + +function almostEqualAssertion(this: any, expected: any, actual: any, message: string): any { + this.assert( + expected.plus(new BigNumber(1)).eq(actual) || + expected.plus(new BigNumber(2)).eq(actual) || + actual.plus(new BigNumber(1)).eq(expected) || + actual.plus(new BigNumber(2)).eq(expected) || + expected.eq(actual), + `${message} expected #{act} to be almost equal #{exp}`, + `${message} expected #{act} to be different from #{exp}`, + expected.toString(), + actual.toString() + ); +} + +export function almostEqual() { + return function (chai: any, utils: any) { + chai.Assertion.overwriteMethod('almostEqual', function (original: any) { + return function (this: any, value: any, message: string) { + if (utils.flag(this, 'bignumber')) { + var expected = new BigNumber(value); + var actual = new BigNumber(this._obj); + almostEqualAssertion.apply(this, [expected, actual, message]); + } else { + original.apply(this, arguments); + } + }; + }); + }; +} diff --git a/test-suites/test-lp/helpers/make-suite.ts b/test-suites/test-lp/helpers/make-suite.ts new file mode 100644 index 00000000..2c005e6e --- /dev/null +++ b/test-suites/test-lp/helpers/make-suite.ts @@ -0,0 +1,191 @@ +import { evmRevert, evmSnapshot, DRE } from '../../../helpers/misc-utils'; +import { Signer } from 'ethers'; +import { + getLendingPool, + getLendingPoolAddressesProvider, + getAaveProtocolDataProvider, + getAToken, + getMintableERC20, + getLendingPoolConfiguratorProxy, + getPriceOracle, + getLendingPoolAddressesProviderRegistry, + getWETHMocked, + getWETHGateway, + getUniswapLiquiditySwapAdapter, + getUniswapRepayAdapter, + getFlashLiquidationAdapter, +} from '../../../helpers/contracts-getters'; +import { eEthereumNetwork, tEthereumAddress } from '../../../helpers/types'; +import { LendingPool } from '../../../types/LendingPool'; +import { AaveProtocolDataProvider } from '../../../types/AaveProtocolDataProvider'; +import { MintableERC20 } from '../../../types/MintableERC20'; +import { AToken } from '../../../types/AToken'; +import { LendingPoolConfigurator } from '../../../types/LendingPoolConfigurator'; + +import chai from 'chai'; +// @ts-ignore +import bignumberChai from 'chai-bignumber'; +import { almostEqual } from './almost-equal'; +import { PriceOracle } from '../../../types/PriceOracle'; +import { LendingPoolAddressesProvider } from '../../../types/LendingPoolAddressesProvider'; +import { LendingPoolAddressesProviderRegistry } from '../../../types/LendingPoolAddressesProviderRegistry'; +import { getEthersSigners } from '../../../helpers/contracts-helpers'; +import { UniswapLiquiditySwapAdapter } from '../../../types/UniswapLiquiditySwapAdapter'; +import { UniswapRepayAdapter } from '../../../types/UniswapRepayAdapter'; +import { getParamPerNetwork } from '../../../helpers/contracts-helpers'; +import { WETH9Mocked } from '../../../types/WETH9Mocked'; +import { WETHGateway } from '../../../types/WETHGateway'; +import { solidity } from 'ethereum-waffle'; +import { UniswapConfig } from '../../../markets/uniswap'; +import { FlashLiquidationAdapter } from '../../../types'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { usingTenderly } from '../../../helpers/tenderly-utils'; + +chai.use(bignumberChai()); +chai.use(almostEqual()); +chai.use(solidity); + +export interface SignerWithAddress { + signer: Signer; + address: tEthereumAddress; +} +export interface TestEnv { + deployer: SignerWithAddress; + users: SignerWithAddress[]; + pool: LendingPool; + configurator: LendingPoolConfigurator; + oracle: PriceOracle; + helpersContract: AaveProtocolDataProvider; + weth: WETH9Mocked; + aWETH: AToken; + dai: MintableERC20; + aDai: AToken; + usdc: MintableERC20; + aave: MintableERC20; + addressesProvider: LendingPoolAddressesProvider; + uniswapLiquiditySwapAdapter: UniswapLiquiditySwapAdapter; + uniswapRepayAdapter: UniswapRepayAdapter; + registry: LendingPoolAddressesProviderRegistry; + wethGateway: WETHGateway; + flashLiquidationAdapter: FlashLiquidationAdapter; +} + +let buidlerevmSnapshotId: string = '0x1'; +const setBuidlerevmSnapshotId = (id: string) => { + buidlerevmSnapshotId = id; +}; + +const testEnv: TestEnv = { + deployer: {} as SignerWithAddress, + users: [] as SignerWithAddress[], + pool: {} as LendingPool, + configurator: {} as LendingPoolConfigurator, + helpersContract: {} as AaveProtocolDataProvider, + oracle: {} as PriceOracle, + weth: {} as WETH9Mocked, + aWETH: {} as AToken, + dai: {} as MintableERC20, + aDai: {} as AToken, + usdc: {} as MintableERC20, + aave: {} as MintableERC20, + addressesProvider: {} as LendingPoolAddressesProvider, + uniswapLiquiditySwapAdapter: {} as UniswapLiquiditySwapAdapter, + uniswapRepayAdapter: {} as UniswapRepayAdapter, + flashLiquidationAdapter: {} as FlashLiquidationAdapter, + registry: {} as LendingPoolAddressesProviderRegistry, + wethGateway: {} as WETHGateway, +} as TestEnv; + +export async function initializeMakeSuite() { + const [_deployer, ...restSigners] = await getEthersSigners(); + const deployer: SignerWithAddress = { + address: await _deployer.getAddress(), + signer: _deployer, + }; + + for (const signer of restSigners) { + testEnv.users.push({ + signer, + address: await signer.getAddress(), + }); + } + testEnv.deployer = deployer; + testEnv.pool = await getLendingPool(); + + testEnv.configurator = await getLendingPoolConfiguratorProxy(); + + testEnv.addressesProvider = await getLendingPoolAddressesProvider(); + + if (process.env.MAINNET_FORK === 'true') { + testEnv.registry = await getLendingPoolAddressesProviderRegistry( + getParamPerNetwork(UniswapConfig.ProviderRegistry, eEthereumNetwork.main) + ); + } else { + testEnv.registry = await getLendingPoolAddressesProviderRegistry(); + testEnv.oracle = await getPriceOracle(); + } + + testEnv.helpersContract = await getAaveProtocolDataProvider(); + + const allTokens = await testEnv.helpersContract.getAllATokens(); + const aDaiAddress = allTokens.find((aToken) => aToken.symbol === 'aUniDAI')?.tokenAddress; + + const aWEthAddress = allTokens.find((aToken) => aToken.symbol === 'aUniWETH')?.tokenAddress; + + const reservesTokens = await testEnv.helpersContract.getAllReservesTokens(); + + const daiAddress = reservesTokens.find((token) => token.symbol === 'UniDAI')?.tokenAddress; + const usdcAddress = reservesTokens.find((token) => token.symbol === 'UniUSDC')?.tokenAddress; + const aaveAddress = reservesTokens.find((token) => token.symbol === 'UniAAVEWETH')?.tokenAddress; + const wethAddress = reservesTokens.find((token) => token.symbol === 'UniWETH')?.tokenAddress; + + if (!aDaiAddress || !aWEthAddress) { + process.exit(1); + } + if (!daiAddress || !usdcAddress || !aaveAddress || !wethAddress) { + process.exit(1); + } + + testEnv.aDai = await getAToken(aDaiAddress); + testEnv.aWETH = await getAToken(aWEthAddress); + + testEnv.dai = await getMintableERC20(daiAddress); + testEnv.usdc = await getMintableERC20(usdcAddress); + testEnv.aave = await getMintableERC20(aaveAddress); + testEnv.weth = await getWETHMocked(wethAddress); + testEnv.wethGateway = await getWETHGateway(); + + testEnv.uniswapLiquiditySwapAdapter = await getUniswapLiquiditySwapAdapter(); + testEnv.uniswapRepayAdapter = await getUniswapRepayAdapter(); + testEnv.flashLiquidationAdapter = await getFlashLiquidationAdapter(); +} + +const setSnapshot = async () => { + const hre = DRE as HardhatRuntimeEnvironment; + if (usingTenderly()) { + setBuidlerevmSnapshotId((await hre.tenderlyRPC.getHead()) || '0x1'); + return; + } + setBuidlerevmSnapshotId(await evmSnapshot()); +}; + +const revertHead = async () => { + const hre = DRE as HardhatRuntimeEnvironment; + if (usingTenderly()) { + await hre.tenderlyRPC.setHead(buidlerevmSnapshotId); + return; + } + await evmRevert(buidlerevmSnapshotId); +}; + +export function makeSuite(name: string, tests: (testEnv: TestEnv) => void) { + describe(name, () => { + before(async () => { + await setSnapshot(); + }); + tests(testEnv); + after(async () => { + await revertHead(); + }); + }); +} diff --git a/test-suites/test-lp/helpers/scenario-engine.ts b/test-suites/test-lp/helpers/scenario-engine.ts new file mode 100644 index 00000000..492fa8b2 --- /dev/null +++ b/test-suites/test-lp/helpers/scenario-engine.ts @@ -0,0 +1,237 @@ +import { TestEnv, SignerWithAddress } from './make-suite'; +import { + mint, + approve, + deposit, + borrow, + withdraw, + repay, + setUseAsCollateral, + swapBorrowRateMode, + rebalanceStableBorrowRate, + delegateBorrowAllowance, +} from './actions'; +import { RateMode } from '../../../helpers/types'; + +export interface Action { + name: string; + args?: any; + expected: string; + revertMessage?: string; +} + +export interface Story { + description: string; + actions: Action[]; +} + +export interface Scenario { + title: string; + description: string; + stories: Story[]; +} + +export const executeStory = async (story: Story, testEnv: TestEnv) => { + for (const action of story.actions) { + const { users } = testEnv; + await executeAction(action, users, testEnv); + } +}; + +const executeAction = async (action: Action, users: SignerWithAddress[], testEnv: TestEnv) => { + const { reserve, user: userIndex, borrowRateMode } = action.args; + const { name, expected, revertMessage } = action; + + if (!name || name === '') { + throw 'Action name is missing'; + } + if (!reserve || reserve === '') { + throw 'Invalid reserve selected for deposit'; + } + if (!userIndex || userIndex === '') { + throw `Invalid user selected to deposit into the ${reserve} reserve`; + } + + if (!expected || expected === '') { + throw `An expected resut for action ${name} is required`; + } + + let rateMode: string = RateMode.None; + + if (borrowRateMode) { + if (borrowRateMode === 'none') { + rateMode = RateMode.None; + } else if (borrowRateMode === 'stable') { + rateMode = RateMode.Stable; + } else if (borrowRateMode === 'variable') { + rateMode = RateMode.Variable; + } else { + //random value, to test improper selection of the parameter + rateMode = '4'; + } + } + + const user = users[parseInt(userIndex)]; + + switch (name) { + case 'mint': + const { amount } = action.args; + + if (!amount || amount === '') { + throw `Invalid amount of ${reserve} to mint`; + } + + await mint(reserve, amount, user); + break; + + case 'approve': + await approve(reserve, user, testEnv); + break; + + case 'deposit': + { + const { amount, sendValue, onBehalfOf: onBehalfOfIndex } = action.args; + const onBehalfOf = onBehalfOfIndex + ? users[parseInt(onBehalfOfIndex)].address + : user.address; + + if (!amount || amount === '') { + throw `Invalid amount to deposit into the ${reserve} reserve`; + } + + await deposit( + reserve, + amount, + user, + onBehalfOf, + sendValue, + expected, + testEnv, + revertMessage + ); + } + break; + + case 'delegateBorrowAllowance': + { + const { amount, toUser: toUserIndex } = action.args; + const toUser = users[parseInt(toUserIndex, 10)].address; + if (!amount || amount === '') { + throw `Invalid amount to deposit into the ${reserve} reserve`; + } + + await delegateBorrowAllowance( + reserve, + amount, + rateMode, + user, + toUser, + expected, + testEnv, + revertMessage + ); + } + break; + + case 'withdraw': + { + const { amount } = action.args; + + if (!amount || amount === '') { + throw `Invalid amount to withdraw from the ${reserve} reserve`; + } + + await withdraw(reserve, amount, user, expected, testEnv, revertMessage); + } + break; + case 'borrow': + { + const { amount, timeTravel, onBehalfOf: onBehalfOfIndex } = action.args; + + const onBehalfOf = onBehalfOfIndex + ? users[parseInt(onBehalfOfIndex)].address + : user.address; + + if (!amount || amount === '') { + throw `Invalid amount to borrow from the ${reserve} reserve`; + } + + await borrow( + reserve, + amount, + rateMode, + user, + onBehalfOf, + timeTravel, + expected, + testEnv, + revertMessage + ); + } + break; + + case 'repay': + { + const { amount, borrowRateMode, sendValue } = action.args; + let { onBehalfOf: onBehalfOfIndex } = action.args; + + if (!amount || amount === '') { + throw `Invalid amount to repay into the ${reserve} reserve`; + } + + let userToRepayOnBehalf: SignerWithAddress; + if (!onBehalfOfIndex || onBehalfOfIndex === '') { + console.log( + 'WARNING: No onBehalfOf specified for a repay action. Defaulting to the repayer address' + ); + userToRepayOnBehalf = user; + } else { + userToRepayOnBehalf = users[parseInt(onBehalfOfIndex)]; + } + + await repay( + reserve, + amount, + rateMode, + user, + userToRepayOnBehalf, + sendValue, + expected, + testEnv, + revertMessage + ); + } + break; + + case 'setUseAsCollateral': + { + const { useAsCollateral } = action.args; + + if (!useAsCollateral || useAsCollateral === '') { + throw `A valid value for useAsCollateral needs to be set when calling setUseReserveAsCollateral on reserve ${reserve}`; + } + await setUseAsCollateral(reserve, user, useAsCollateral, expected, testEnv, revertMessage); + } + break; + + case 'swapBorrowRateMode': + await swapBorrowRateMode(reserve, user, rateMode, expected, testEnv, revertMessage); + break; + + case 'rebalanceStableBorrowRate': + { + const { target: targetIndex } = action.args; + + if (!targetIndex || targetIndex === '') { + throw `A target must be selected when trying to rebalance a stable rate`; + } + const target = users[parseInt(targetIndex)]; + + await rebalanceStableBorrowRate(reserve, user, target, expected, testEnv, revertMessage); + } + break; + + default: + throw `Invalid action requested: ${name}`; + } +}; diff --git a/test-suites/test-lp/helpers/scenarios/borrow-negatives.json b/test-suites/test-lp/helpers/scenarios/borrow-negatives.json new file mode 100644 index 00000000..811b5ed6 --- /dev/null +++ b/test-suites/test-lp/helpers/scenarios/borrow-negatives.json @@ -0,0 +1,142 @@ +{ + "title": "LendingPool: Borrow negatives (reverts)", + "description": "Test cases for the deposit function.", + "stories": [ + { + "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 UNIWETH as collateral and tries to borrow 100 UNIDAI with rate mode NONE (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "none", + "user": "1" + }, + "expected": "revert", + "revertMessage": "Invalid interest rate mode selected" + } + ] + }, + { + "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 UNIWETH as collateral and tries to borrow 100 UNIDAI with an invalid rate mode (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "invalid", + "user": "1" + }, + "expected": "revert", + "revertMessage": "Invalid interest rate mode selected" + } + ] + } + ] +} diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json b/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json new file mode 100644 index 00000000..40b96803 --- /dev/null +++ b/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json @@ -0,0 +1,656 @@ +{ + "title": "LendingPool: Borrow/repay (stable rate)", + "description": "Test cases for the borrow function, stable mode.", + "stories": [ + { + "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 UNIWETH as collateral and borrows 100 UNIDAI at stable rate", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 tries to borrow the rest of the UNIDAI liquidity (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "900", + "borrowRateMode": "stable", + "user": "1" + }, + "expected": "revert", + "revertMessage": "There is not enough collateral to cover a new borrow" + } + ] + }, + { + "description": "User 1 repays half of the UNIDAI borrow after one year", + "actions": [ + { + "name": "mint", + "description": "Mint 10 UNIDAI to cover the interest", + "args": { + "reserve": "UNIDAI", + "amount": "10", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "50", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 repays the rest of the UNIDAI borrow after one year", + "actions": [ + { + "name": "mint", + "description": "Mint 15 UNIDAI to cover the interest", + "args": { + "reserve": "UNIDAI", + "amount": "15", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws the deposited UNIDAI plus interest", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 1000 UNIDAI, user 2 tries to borrow 1000 UNIDAI at a stable rate without any collateral (revert expected) User 1 withdrawws", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "borrowRateMode": "stable", + "user": "2" + }, + "expected": "revert", + "revertMessage": "The collateral balance is 0" + }, + { + "name": "withdraw", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1000 UNIDAI, user 1,2,3,4 deposit 1 UNIWETH each and borrow 100 UNIDAI at stable rate. Everything is repaid, user 0 withdraws", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "2" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "2" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "2" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "2", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "3" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "3" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "3" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "3", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "4" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "4" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "4" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "4", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 15 UNIDAI to cover the interest", + "args": { + "reserve": "UNIDAI", + "amount": "15", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 20 UNIDAI to cover the interest", + "args": { + "reserve": "UNIDAI", + "amount": "20", + "user": "2" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "2" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "2", + "onBehalfOf": "2", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 30 UNIDAI to cover the interest", + "args": { + "reserve": "UNIDAI", + "amount": "30", + "user": "3" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "3" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "3", + "onBehalfOf": "3", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 30 UNIDAI to cover the interest", + "args": { + "reserve": "UNIDAI", + "amount": "30", + "user": "4" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "4" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "4", + "onBehalfOf": "4", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 2 UNIWETH and borrow 100 UNIDAI at stable rate first, then 100 UNIDAI at variable rate, repays everything. User 0 withdraws", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "2", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "2", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 50 UNIDAI to cover the interest", + "args": { + "reserve": "UNIDAI", + "amount": "50", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json b/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json new file mode 100644 index 00000000..dd5936f9 --- /dev/null +++ b/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json @@ -0,0 +1,945 @@ +{ + "title": "LendingPool: Borrow/repay (variable rate)", + "description": "Test cases for the borrow function, variable mode.", + "stories": [ + { + "description": "User 2 deposits 1 UNIDAI to account for rounding errors", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1", + "user": "2" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "2" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1", + "user": "2" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 UNIWETH as collateral and borrows 100 UNIDAI at variable rate", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 tries to borrow the rest of the UNIDAI liquidity (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "900", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "revert", + "revertMessage": "There is not enough collateral to cover a new borrow" + } + ] + }, + { + "description": "User 1 tries to repay 0 UNIDAI (revert expected)", + "actions": [ + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "0", + "user": "1", + "onBehalfOf": "1" + }, + "expected": "revert", + "revertMessage": "Amount must be greater than 0" + } + ] + }, + { + "description": "User 1 repays a small amount of UNIDAI, enough to cover a small part of the interest", + "actions": [ + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "1.25", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 repays the UNIDAI borrow after one year", + "actions": [ + { + "name": "mint", + "description": "Mint 10 UNIDAI to cover the interest", + "args": { + "reserve": "UNIDAI", + "amount": "10", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws the deposited UNIDAI plus interest", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 withdraws the collateral", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIWETH", + "amount": "-1", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 2 deposits a small amount of UNIWETH to account for rounding errors", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "0.001", + "user": "2" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "2" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "0.001", + "user": "2" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1 UNIWETH, user 1 deposits 100 UNILINKWETH as collateral and borrows 0.5 WETH at variable rate", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNILINKWETH", + "amount": "100", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNILINKWETH", + "user": "1" + }, + "expected": "success" + }, + + { + "name": "deposit", + "args": { + "reserve": "UNILINKWETH", + "amount": "100", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIWETH", + "amount": "0.5", + "borrowRateMode": "variable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 tries to repay 0 WETH", + "actions": [ + { + "name": "repay", + "args": { + "reserve": "UNIWETH", + "amount": "0", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "revert", + "revertMessage": "Amount must be greater than 0" + } + ] + }, + { + "description": "User 2 tries to repay everything on behalf of user 1 using uint(-1) (revert expected)", + "actions": [ + { + "name": "repay", + "args": { + "reserve": "UNIWETH", + "amount": "-1", + "user": "2", + "borrowRateMode": "variable", + "onBehalfOf": "1" + }, + "expected": "revert", + "revertMessage": "To repay on behalf of an user an explicit amount to repay is needed" + } + ] + }, + { + "description": "User 3 repays a small amount of UNIWETH on behalf of user 1", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "3" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "3" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIWETH", + "amount": "0.2", + "user": "3", + "borrowRateMode": "variable", + "onBehalfOf": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 repays the UNIWETH borrow after one year", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "2" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "2" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIWETH", + "amount": "-1", + "borrowRateMode": "variable", + "user": "1", + "onBehalfOf": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws the deposited UNIWETH plus interest", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIWETH", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 withdraws the collateral", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNILINKWETH", + "amount": "-1", + "user": "1" + }, + "expected": "success" + } + ] + }, + + { + "description": "User 2 deposits 1 UNIUSDC to account for rounding errors", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIUSDC", + "amount": "1", + "user": "2" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIUSDC", + "user": "2" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIUSDC", + "amount": "1", + "user": "2" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1000 UNIUSDC, user 1 deposits 1 UNIWETH as collateral and borrows 100 UNIUSDC at variable rate", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIUSDC", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIUSDC", + "amount": "100", + "borrowRateMode": "variable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 tries to borrow the rest of the UNIUSDC liquidity (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "UNIUSDC", + "amount": "900", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "revert", + "revertMessage": "There is not enough collateral to cover a new borrow" + } + ] + }, + { + "description": "User 1 repays the UNIUSDC borrow after one year", + "actions": [ + { + "name": "mint", + "description": "Mint 10 UNIUSDC to cover the interest", + "args": { + "reserve": "UNIUSDC", + "amount": "10", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIUSDC", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIUSDC", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws the deposited UNIUSDC plus interest", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIUSDC", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 withdraws the collateral", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIWETH", + "amount": "-1", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 1000 UNIDAI, user 3 tries to borrow 1000 UNIDAI without any collateral (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "borrowRateMode": "variable", + "user": "3" + }, + "expected": "revert", + "revertMessage": "The collateral balance is 0" + } + ] + }, + { + "description": "user 3 deposits 0.1 WETH collateral to borrow 100 UNIDAI; 0.1 WETH is not enough to borrow 100 UNIDAI (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "0.1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "0.1", + "user": "3" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "3" + }, + "expected": "revert", + "revertMessage": "There is not enough collateral to cover a new borrow" + } + ] + }, + { + "description": "user 3 withdraws the 0.1 WETH", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIWETH", + "amount": "-1", + "user": "3" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 1000 UNIUSDC, user 3 tries to borrow 1000 UNIUSDC without any collateral (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIUSDC", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "borrowRateMode": "variable", + "user": "3" + }, + "expected": "revert", + "revertMessage": "The collateral balance is 0" + } + ] + }, + { + "description": "user 3 deposits 0.1 WETH collateral to borrow 100 UNIUSDC; 0.1 WETH is not enough to borrow 100 UNIUSDC (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "3" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "0.1", + "user": "3" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIUSDC", + "amount": "100", + "borrowRateMode": "variable", + "user": "3" + }, + "expected": "revert", + "revertMessage": "There is not enough collateral to cover a new borrow" + } + ] + }, + { + "description": "user 3 withdraws the 0.1 WETH", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIWETH", + "amount": "-1", + "user": "3" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1000 UNIDAI, user 6 deposits 2 UNIWETH and borrow 100 UNIDAI at variable rate first, then 100 UNIDAI at stable rate, repays everything. User 0 withdraws", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "2", + "user": "6" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "6" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "2", + "user": "6" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "6", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "6", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 50 UNIDAI to cover the interest", + "args": { + "reserve": "UNIDAI", + "amount": "50", + "user": "6" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "6" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "6", + "onBehalfOf": "6", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "6", + "onBehalfOf": "6", + "borrowRateMode": "variable" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-lp/helpers/scenarios/credit-delegation.json b/test-suites/test-lp/helpers/scenarios/credit-delegation.json new file mode 100644 index 00000000..b1bf7479 --- /dev/null +++ b/test-suites/test-lp/helpers/scenarios/credit-delegation.json @@ -0,0 +1,157 @@ +{ + "title": "LendingPool: credit delegation", + "description": "Test cases for the credit delegation related functions.", + "stories": [ + { + "description": "User 3 deposits 1000 UNIWETH. User 0 deposits 1000 UNIDAI, user 0 delegates borrowing of 1 UNIWETH on variable to user 4, user 4 borrows 1 UNIWETH variable on behalf of user 0", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1000", + "user": "3" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "3" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1000", + "user": "3" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "delegateBorrowAllowance", + "args": { + "reserve": "UNIWETH", + "amount": "2", + "user": "0", + "borrowRateMode": "variable", + "toUser": "4" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "4", + "onBehalfOf": "0", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 4 trying to borrow 1 UNIWETH stable on behalf of user 0, revert expected", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "4", + "onBehalfOf": "0", + "borrowRateMode": "stable" + }, + "expected": "revert", + "revertMessage": "59" + } + ] + }, + { + "description": "User 0 delegates borrowing of 1 UNIWETH to user 4, user 4 borrows 3 UNIWETH variable on behalf of user 0, revert expected", + "actions": [ + { + "name": "delegateBorrowAllowance", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "0", + "borrowRateMode": "variable", + "toUser": "4" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIWETH", + "amount": "3", + "user": "4", + "onBehalfOf": "0", + "borrowRateMode": "variable" + }, + "expected": "revert", + "revertMessage": "59" + } + ] + }, + { + "description": "User 0 delegates borrowing of 1 UNIWETH on stable to user 2, user 2 borrows 1 UNIWETH stable on behalf of user 0", + "actions": [ + { + "name": "delegateBorrowAllowance", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "0", + "borrowRateMode": "stable", + "toUser": "2" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "2", + "onBehalfOf": "0", + "borrowRateMode": "stable" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-lp/helpers/scenarios/deposit.json b/test-suites/test-lp/helpers/scenarios/deposit.json new file mode 100644 index 00000000..a741fe6f --- /dev/null +++ b/test-suites/test-lp/helpers/scenarios/deposit.json @@ -0,0 +1,266 @@ +{ + "title": "LendingPool: Deposit", + "description": "Test cases for the deposit function.", + "stories": [ + { + "description": "User 0 Deposits 1000 UNIDAI in an empty reserve", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 1000 UNIDAI after user 0", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1000 UNIUSDC in an empty reserve", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIUSDC", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 1000 UNIUSDC after user 0", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIUSDC", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 deposits 1 UNIWETH in an empty reserve", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 1 UNIWETH after user 0", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 deposits 0 UNIWETH (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "0", + "user": "1" + }, + "expected": "revert", + "revertMessage": "Amount must be greater than 0" + } + ] + }, + { + "description": "User 1 deposits 0 UNIDAI", + "actions": [ + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "0", + "user": "1" + }, + "expected": "revert", + "revertMessage": "Amount must be greater than 0" + } + ] + }, + { + "description": "User 1 deposits 100 UNIDAI on behalf of user 2, user 2 tries to borrow 0.1 UNIWETH", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "user": "1", + "onBehalfOf": "2" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIWETH", + "amount": "0.1", + "borrowRateMode": "variable", + "user": "2" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json b/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json new file mode 100644 index 00000000..8d6e4b99 --- /dev/null +++ b/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json @@ -0,0 +1,198 @@ +{ + "title": "LendingPool: Rebalance stable rate", + "description": "Test cases for the rebalanceStableBorrowRate() function.", + "stories": [ + { + "description": "User 0 tries to rebalance user 1 who has no borrows in progress (revert expected)", + "actions": [ + { + "name": "rebalanceStableBorrowRate", + "args": { + "reserve": "UNIUSDC", + "user": "0", + "target": "1" + }, + "expected": "revert", + "revertMessage": "User does not have any stable rate loan for this reserve" + } + ] + }, + { + "description": "User 0 deposits 1000 UNIUSDC, user 1 deposits 7 UNIWETH, borrows 250 UNIUSDC at a stable rate, user 0 rebalances user 1 (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIUSDC", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "7", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "7", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIUSDC", + "amount": "250", + "borrowRateMode": "stable", + "user": "1" + }, + "expected": "success" + }, + { + "name": "rebalanceStableBorrowRate", + "args": { + "reserve": "UNIUSDC", + "user": "0", + "target": "1" + }, + "expected": "revert", + "revertMessage": "The user borrow is variable and cannot be rebalanced" + } + ] + }, + { + "description": "User 1 borrows another 200 at variable, user 0 tries to rebalance but the conditions are not met (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "UNIUSDC", + "amount": "200", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "success" + }, + { + "name": "rebalanceStableBorrowRate", + "args": { + "reserve": "UNIUSDC", + "user": "0", + "target": "1" + }, + "expected": "revert", + "revertMessage": "Interest rate rebalance conditions were not met" + } + ] + }, + { + "description": "User 1 borrows another 200 at variable, user 0 tries to rebalance but the conditions are not met (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "UNIUSDC", + "amount": "200", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "success" + }, + { + "name": "rebalanceStableBorrowRate", + "args": { + "reserve": "UNIUSDC", + "user": "0", + "target": "1" + }, + "expected": "revert", + "revertMessage": "Interest rate rebalance conditions were not met" + } + ] + }, + { + "description": "User 1 borrows another 100 at variable, user 0 tries to rebalance but the conditions are not met (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "UNIUSDC", + "amount": "280", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "success" + }, + { + "name": "rebalanceStableBorrowRate", + "args": { + "reserve": "UNIUSDC", + "user": "0", + "target": "1" + }, + "expected": "revert", + "revertMessage": "Interest rate rebalance conditions were not met" + } + ] + }, + + { + "description": "User 1 borrows the remaining UNIUSDC (usage ratio = 100%) at variable. User 0 rebalances user 1", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "UNIUSDC", + "amount": "20", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "success" + }, + { + "name": "rebalanceStableBorrowRate", + "args": { + "reserve": "UNIUSDC", + "user": "0", + "target": "1" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json b/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json new file mode 100644 index 00000000..f573fe81 --- /dev/null +++ b/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json @@ -0,0 +1,236 @@ +{ + "title": "LendingPool: Usage as collateral", + "description": "Test cases for the setUserUseReserveAsCollateral() function.", + "stories": [ + { + "description": "User 0 Deposits 1000 UNIDAI, disables UNIDAI as collateral", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "setUseAsCollateral", + "args": { + "reserve": "UNIDAI", + "user": "0", + "useAsCollateral": "false" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 Deposits 2 UNIWETH, disables UNIWETH as collateral, borrows 400 UNIDAI (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "2", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "2", + "user": "1" + }, + "expected": "success" + }, + { + "name": "setUseAsCollateral", + "args": { + "reserve": "UNIWETH", + "user": "1", + "useAsCollateral": "false" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "400", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "revert", + "revertMessage": "The collateral balance is 0" + } + ] + }, + { + "description": "User 1 enables UNIWETH as collateral, borrows 400 UNIDAI", + "actions": [ + { + "name": "setUseAsCollateral", + "args": { + "reserve": "UNIWETH", + "user": "1", + "useAsCollateral": "true" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "400", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 disables UNIWETH as collateral (revert expected)", + "actions": [ + { + "name": "setUseAsCollateral", + "args": { + "reserve": "UNIWETH", + "user": "1", + "useAsCollateral": "false" + }, + "expected": "revert", + "revertMessage": "User deposit is already being used as collateral" + } + ] + }, + { + "description": "User 1 Deposits 10 UNILINKWETH, disables UNIWETH as collateral. Should revert as 10 UNILINKWETH are not enough to cover the debt (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNILINKWETH", + "amount": "10", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNILINKWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNILINKWETH", + "amount": "10", + "user": "1" + }, + "expected": "success" + }, + { + "name": "setUseAsCollateral", + "args": { + "reserve": "UNIWETH", + "user": "1", + "useAsCollateral": "false" + }, + "expected": "revert" + } + ] + }, + { + "description": "User 1 Deposits 640 more UNILINKWETH (enough to cover the UNIDAI debt), disables UNIWETH as collateral", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNILINKWETH", + "amount": "640", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNILINKWETH", + "amount": "640", + "user": "1" + }, + "expected": "success" + }, + { + "name": "setUseAsCollateral", + "args": { + "reserve": "UNIWETH", + "user": "1", + "useAsCollateral": "false" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 disables UNILINKWETH as collateral (revert expected)", + "actions": [ + { + "name": "setUseAsCollateral", + "args": { + "reserve": "UNILINKWETH", + "user": "1", + "useAsCollateral": "false" + }, + "expected": "revert" + } + ] + }, + { + "description": "User 1 reenables UNIWETH as collateral", + "actions": [ + { + "name": "setUseAsCollateral", + "args": { + "reserve": "UNIWETH", + "user": "1", + "useAsCollateral": "true" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json b/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json new file mode 100644 index 00000000..2b175236 --- /dev/null +++ b/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json @@ -0,0 +1,167 @@ +{ + "title": "LendingPool: Swap rate mode", + "description": "Test cases for the swapBorrowRateMode() function.", + "stories": [ + { + "description": "User 0 tries to swap rate mode without any variable rate loan in progress (revert expected)", + "actions": [ + { + "name": "swapBorrowRateMode", + "args": { + "reserve": "UNIDAI", + "user": "1", + "borrowRateMode": "variable" + }, + "expected": "revert", + "revertMessage": "User does not have a variable rate loan in progress on this reserve" + } + ] + }, + { + "description": "User 0 tries to swap rate mode without any stable rate loan in progress (revert expected)", + "actions": [ + { + "name": "swapBorrowRateMode", + "args": { + "reserve": "UNIDAI", + "user": "1", + "borrowRateMode": "stable" + }, + "expected": "revert", + "revertMessage": "User does not have a stable rate loan in progress on this reserve" + } + ] + }, + { + "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 2 WETH as collateral, borrows 100 UNIDAI at variable rate and swaps to stable after one year", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "2", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "2", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "swapBorrowRateMode", + "args": { + "reserve": "UNIDAI", + "user": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 borrows another 100 UNIDAI, and swaps back to variable after one year, repays the loan", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "borrowRateMode": "stable", + "user": "1", + "timeTravel": "365" + }, + "expected": "success" + }, + { + "name": "swapBorrowRateMode", + "args": { + "reserve": "UNIDAI", + "user": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "mint", + "description": "Mint 50 UNIDAI to cover the interest", + "args": { + "reserve": "UNIDAI", + "amount": "50", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json b/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json new file mode 100644 index 00000000..5eca78d4 --- /dev/null +++ b/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json @@ -0,0 +1,114 @@ +{ + "title": "LendingPool: Redeem negative test cases", + "description": "Redeem function.", + "stories": [ + { + "description": "Users 0 Deposits 1000 UNIDAI and tries to redeem 0 UNIDAI (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + + { + "name": "withdraw", + "args": { + "reserve": "UNIDAI", + "amount": "0", + "user": "0" + }, + "expected": "revert", + "revertMessage": "Amount to redeem needs to be > 0" + } + ] + }, + { + "description": "Users 0 tries to redeem 1100 UNIDAI from the 1000 UNIDAI deposited (revert expected)", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIDAI", + "amount": "1100", + "user": "0" + }, + "expected": "revert", + "revertMessage": "User cannot redeem more than the available balance" + } + ] + }, + { + "description": "Users 1 deposits 1 UNIWETH, borrows 100 UNIDAI, tries to redeem the 1 UNIWETH deposited (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "user": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "UNIWETH", + "amount": "-1", + "user": "1" + }, + "expected": "revert", + "revertMessage": "Transfer cannot be allowed." + } + ] + } + ] +} diff --git a/test-suites/test-lp/helpers/scenarios/withdraw.json b/test-suites/test-lp/helpers/scenarios/withdraw.json new file mode 100644 index 00000000..461c7db2 --- /dev/null +++ b/test-suites/test-lp/helpers/scenarios/withdraw.json @@ -0,0 +1,340 @@ +{ + "title": "LendingPool: withdraw", + "description": "withdraw function.", + "stories": [ + { + "description": "User 0 Deposits 1000 UNIDAI in an empty reserve", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws half of the deposited UNIDAI", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIDAI", + "amount": "500", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws remaining half of the deposited UNIDAI", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 Deposits 1000 UNIUSDC in an empty reserve", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIUSDC", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws half of the deposited UNIUSDC", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIUSDC", + "amount": "500", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws remaining half of the deposited UNIUSDC", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIUSDC", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 Deposits 1 UNIWETH in an empty reserve", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws half of the deposited UNIWETH", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIWETH", + "amount": "0.5", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 withdraws remaining half of the deposited WETH", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIWETH", + "amount": "-1", + "user": "0" + }, + "expected": "success" + } + ] + }, + { + "description": "Users 0 and 1 Deposit 1000 UNIDAI, both withdraw", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIDAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "0" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "UNIDAI", + "amount": "-1", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "Users 0 deposits 1000 UNIDAI, user 1 Deposit 1000 UNIUSDC and 1 UNIWETH, borrows 100 UNIDAI. User 1 tries to withdraw all the UNIUSDC", + "actions": [ + { + "name": "deposit", + "args": { + "reserve": "UNIDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIUSDC", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIUSDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "UNIWETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "UNIWETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "UNIDAI", + "amount": "100", + "user": "1", + "borrowRateMode": "stable" + }, + "expected": "success" + }, + { + "name": "withdraw", + "args": { + "reserve": "UNIUSDC", + "amount": "-1", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "Users 1 tries to withdraw 0.05 UNIWETH, which does not bring the HF below 1", + "actions": [ + { + "name": "withdraw", + "args": { + "reserve": "UNIWETH", + "amount": "0.05", + "user": "1" + }, + "expected": "success" + } + ] + } + ] +} diff --git a/test-suites/test-lp/helpers/utils/calculations.ts b/test-suites/test-lp/helpers/utils/calculations.ts new file mode 100644 index 00000000..dc77b5db --- /dev/null +++ b/test-suites/test-lp/helpers/utils/calculations.ts @@ -0,0 +1,1434 @@ +import BigNumber from 'bignumber.js'; +import { ONE_YEAR, RAY, MAX_UINT_AMOUNT, PERCENTAGE_FACTOR } from '../../../../helpers/constants'; +import { + IReserveParams, + iUniswapPoolAssets, + RateMode, + tEthereumAddress, +} from '../../../../helpers/types'; +import './math'; +import { ReserveData, UserReserveData } from './interfaces'; + +export const strToBN = (amount: string): BigNumber => new BigNumber(amount); + +interface Configuration { + reservesParams: iUniswapPoolAssets; +} + +export const configuration: Configuration = {}; + +export const calcExpectedUserDataAfterDeposit = ( + amountDeposited: string, + reserveDataBeforeAction: ReserveData, + reserveDataAfterAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber, + currentTimestamp: BigNumber, + txCost: BigNumber +): UserReserveData => { + const expectedUserData = {}; + + expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; + expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt; + expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; + expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; + expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated; + + expectedUserData.liquidityRate = reserveDataAfterAction.liquidityRate; + + expectedUserData.scaledATokenBalance = calcExpectedScaledATokenBalance( + userDataBeforeAction, + reserveDataAfterAction.liquidityIndex, + new BigNumber(amountDeposited), + new BigNumber(0) + ); + expectedUserData.currentATokenBalance = calcExpectedATokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ).plus(amountDeposited); + + if (userDataBeforeAction.currentATokenBalance.eq(0)) { + expectedUserData.usageAsCollateralEnabled = true; + } else { + expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled; + } + + expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; + expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(amountDeposited); + + expectedUserData.currentStableDebt = expectedUserData.principalStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedUserData.currentVariableDebt = expectedUserData.principalStableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + return expectedUserData; +}; + +export const calcExpectedUserDataAfterWithdraw = ( + amountWithdrawn: string, + reserveDataBeforeAction: ReserveData, + reserveDataAfterAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber, + currentTimestamp: BigNumber, + txCost: BigNumber +): UserReserveData => { + const expectedUserData = {}; + + const aTokenBalance = calcExpectedATokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + if (amountWithdrawn == MAX_UINT_AMOUNT) { + amountWithdrawn = aTokenBalance.toFixed(0); + } + + expectedUserData.scaledATokenBalance = calcExpectedScaledATokenBalance( + userDataBeforeAction, + reserveDataAfterAction.liquidityIndex, + new BigNumber(0), + new BigNumber(amountWithdrawn) + ); + + expectedUserData.currentATokenBalance = aTokenBalance.minus(amountWithdrawn); + + expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; + expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt; + + expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; + expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; + expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated; + + expectedUserData.liquidityRate = reserveDataAfterAction.liquidityRate; + + if (userDataBeforeAction.currentATokenBalance.eq(0)) { + expectedUserData.usageAsCollateralEnabled = true; + } else { + //if the user is withdrawing everything, usageAsCollateralEnabled must be false + if (expectedUserData.currentATokenBalance.eq(0)) { + expectedUserData.usageAsCollateralEnabled = false; + } else { + expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled; + } + } + + expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountWithdrawn); + + return expectedUserData; +}; + +export const calcExpectedReserveDataAfterDeposit = ( + amountDeposited: string, + reserveDataBeforeAction: ReserveData, + txTimestamp: BigNumber +): ReserveData => { + const expectedReserveData: ReserveData = {}; + + expectedReserveData.address = reserveDataBeforeAction.address; + + expectedReserveData.totalLiquidity = new BigNumber(reserveDataBeforeAction.totalLiquidity).plus( + amountDeposited + ); + expectedReserveData.availableLiquidity = new BigNumber( + reserveDataBeforeAction.availableLiquidity + ).plus(amountDeposited); + + expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate; + expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( + reserveDataBeforeAction, + txTimestamp + ); + expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + expectedReserveData.totalVariableDebt = calcExpectedTotalVariableDebt( + reserveDataBeforeAction, + expectedReserveData.variableBorrowIndex + ); + + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; + expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt; + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + const rates = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + expectedReserveData.utilizationRate, + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.averageStableBorrowRate + ); + expectedReserveData.liquidityRate = rates[0]; + expectedReserveData.stableBorrowRate = rates[1]; + expectedReserveData.variableBorrowRate = rates[2]; + + return expectedReserveData; +}; + +export const calcExpectedReserveDataAfterWithdraw = ( + amountWithdrawn: string, + reserveDataBeforeAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber +): ReserveData => { + const expectedReserveData: ReserveData = {}; + + expectedReserveData.address = reserveDataBeforeAction.address; + + if (amountWithdrawn == MAX_UINT_AMOUNT) { + amountWithdrawn = calcExpectedATokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ).toFixed(); + } + + expectedReserveData.availableLiquidity = new BigNumber( + reserveDataBeforeAction.availableLiquidity + ).minus(amountWithdrawn); + + expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt; + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; + + expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( + reserveDataBeforeAction, + txTimestamp + ); + expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate; + + expectedReserveData.totalLiquidity = new BigNumber(reserveDataBeforeAction.availableLiquidity) + .minus(amountWithdrawn) + .plus(expectedReserveData.totalVariableDebt) + .plus(expectedReserveData.totalStableDebt); + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + const rates = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + expectedReserveData.utilizationRate, + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.averageStableBorrowRate + ); + expectedReserveData.liquidityRate = rates[0]; + expectedReserveData.stableBorrowRate = rates[1]; + expectedReserveData.variableBorrowRate = rates[2]; + + return expectedReserveData; +}; + +export const calcExpectedReserveDataAfterBorrow = ( + amountBorrowed: string, + borrowRateMode: string, + reserveDataBeforeAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber, + currentTimestamp: BigNumber +): ReserveData => { + const expectedReserveData = {}; + + expectedReserveData.address = reserveDataBeforeAction.address; + + const amountBorrowedBN = new BigNumber(amountBorrowed); + + expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity.minus( + amountBorrowedBN + ); + + expectedReserveData.lastUpdateTimestamp = txTimestamp; + + if (borrowRateMode == RateMode.Stable) { + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; + + const expectedVariableDebtAfterTx = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + const expectedStableDebtUntilTx = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + + expectedReserveData.principalStableDebt = expectedStableDebtUntilTx.plus(amountBorrowedBN); + + expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( + reserveDataBeforeAction.averageStableBorrowRate, + expectedStableDebtUntilTx, + amountBorrowedBN, + reserveDataBeforeAction.stableBorrowRate + ); + + const totalLiquidityAfterTx = expectedReserveData.availableLiquidity + .plus(expectedReserveData.principalStableDebt) + .plus(expectedVariableDebtAfterTx); + + const utilizationRateAfterTx = calcExpectedUtilizationRate( + expectedReserveData.principalStableDebt, //the expected principal debt is the total debt immediately after the tx + expectedVariableDebtAfterTx, + totalLiquidityAfterTx + ); + + const ratesAfterTx = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + utilizationRateAfterTx, + expectedReserveData.principalStableDebt, + expectedVariableDebtAfterTx, + expectedReserveData.averageStableBorrowRate + ); + + expectedReserveData.liquidityRate = ratesAfterTx[0]; + + expectedReserveData.stableBorrowRate = ratesAfterTx[1]; + + expectedReserveData.variableBorrowRate = ratesAfterTx[2]; + + expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( + expectedReserveData.principalStableDebt, + expectedReserveData.averageStableBorrowRate, + txTimestamp, + currentTimestamp + ); + + expectedReserveData.totalVariableDebt = reserveDataBeforeAction.scaledVariableDebt.rayMul( + calcExpectedReserveNormalizedDebt( + expectedReserveData.variableBorrowRate, + expectedReserveData.variableBorrowIndex, + txTimestamp, + currentTimestamp + ) + ); + + expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity + .plus(expectedReserveData.totalVariableDebt) + .plus(expectedReserveData.totalStableDebt); + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + } else { + expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt; + + const totalStableDebtAfterTx = calcExpectedStableDebtTokenBalance( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + + expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + currentTimestamp + ); + + expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate; + + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.plus( + amountBorrowedBN.rayDiv(expectedReserveData.variableBorrowIndex) + ); + + const totalVariableDebtAfterTx = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + const utilizationRateAfterTx = calcExpectedUtilizationRate( + totalStableDebtAfterTx, + totalVariableDebtAfterTx, + expectedReserveData.availableLiquidity + .plus(totalStableDebtAfterTx) + .plus(totalVariableDebtAfterTx) + ); + + const rates = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + utilizationRateAfterTx, + totalStableDebtAfterTx, + totalVariableDebtAfterTx, + expectedReserveData.averageStableBorrowRate + ); + + expectedReserveData.liquidityRate = rates[0]; + + expectedReserveData.stableBorrowRate = rates[1]; + + expectedReserveData.variableBorrowRate = rates[2]; + + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + calcExpectedReserveNormalizedDebt( + expectedReserveData.variableBorrowRate, + expectedReserveData.variableBorrowIndex, + txTimestamp, + currentTimestamp + ) + ); + + expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity + .plus(expectedReserveData.totalStableDebt) + .plus(expectedReserveData.totalVariableDebt); + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + } + + return expectedReserveData; +}; + +export const calcExpectedReserveDataAfterRepay = ( + amountRepaid: string, + borrowRateMode: RateMode, + reserveDataBeforeAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber, + currentTimestamp: BigNumber +): ReserveData => { + const expectedReserveData: ReserveData = {}; + + expectedReserveData.address = reserveDataBeforeAction.address; + + let amountRepaidBN = new BigNumber(amountRepaid); + + const userStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + const userVariableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + //if amount repaid == MAX_UINT_AMOUNT, user is repaying everything + if (amountRepaidBN.abs().eq(MAX_UINT_AMOUNT)) { + if (borrowRateMode == RateMode.Stable) { + amountRepaidBN = userStableDebt; + } else { + amountRepaidBN = userVariableDebt; + } + } + + expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( + reserveDataBeforeAction, + txTimestamp + ); + expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( + reserveDataBeforeAction, + txTimestamp + ); + + if (borrowRateMode == RateMode.Stable) { + const expectedDebt = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + + expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = expectedDebt.minus( + amountRepaidBN + ); + + //due to accumulation errors, the total stable debt might be smaller than the last user debt. + //in this case we simply set the total supply and avg stable rate to 0. + if (expectedReserveData.totalStableDebt.lt(0)) { + expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = expectedReserveData.averageStableBorrowRate = new BigNumber( + 0 + ); + } else { + expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( + reserveDataBeforeAction.averageStableBorrowRate, + expectedDebt, + amountRepaidBN.negated(), + userDataBeforeAction.stableBorrowRate + ); + + //also due to accumulation errors, the final avg stable rate when the last user repays might be negative. + //if that is the case, it means a small leftover of total stable debt is left, which can be erased. + + if (expectedReserveData.averageStableBorrowRate.lt(0)) { + expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = expectedReserveData.averageStableBorrowRate = new BigNumber( + 0 + ); + } + } + + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; + + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + } else { + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.minus( + amountRepaidBN.rayDiv(expectedReserveData.variableBorrowIndex) + ); + + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt; + expectedReserveData.totalStableDebt = reserveDataBeforeAction.totalStableDebt; + + expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate; + } + + expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity.plus( + amountRepaidBN + ); + + expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity + .plus(expectedReserveData.totalStableDebt) + .plus(expectedReserveData.totalVariableDebt); + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + + const rates = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + expectedReserveData.utilizationRate, + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.averageStableBorrowRate + ); + expectedReserveData.liquidityRate = rates[0]; + + expectedReserveData.stableBorrowRate = rates[1]; + + expectedReserveData.variableBorrowRate = rates[2]; + + expectedReserveData.lastUpdateTimestamp = txTimestamp; + + return expectedReserveData; +}; + +export const calcExpectedUserDataAfterBorrow = ( + amountBorrowed: string, + interestRateMode: string, + reserveDataBeforeAction: ReserveData, + expectedDataAfterAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber, + currentTimestamp: BigNumber +): UserReserveData => { + const expectedUserData = {}; + + const amountBorrowedBN = new BigNumber(amountBorrowed); + + if (interestRateMode == RateMode.Stable) { + const stableDebtUntilTx = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedUserData.principalStableDebt = stableDebtUntilTx.plus(amountBorrowed); + expectedUserData.stableRateLastUpdated = txTimestamp; + + expectedUserData.stableBorrowRate = calcExpectedUserStableRate( + stableDebtUntilTx, + userDataBeforeAction.stableBorrowRate, + amountBorrowedBN, + reserveDataBeforeAction.stableBorrowRate + ); + + expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance( + expectedUserData.principalStableDebt, + expectedUserData.stableBorrowRate, + txTimestamp, + currentTimestamp + ); + + expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt; + } else { + expectedUserData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.plus( + amountBorrowedBN.rayDiv(expectedDataAfterAction.variableBorrowIndex) + ); + + expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; + + expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; + + expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated; + + expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + currentTimestamp + ); + } + + expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( + expectedDataAfterAction, + expectedUserData, + currentTimestamp + ); + + expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; + + expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled; + + expectedUserData.currentATokenBalance = calcExpectedATokenBalance( + expectedDataAfterAction, + userDataBeforeAction, + currentTimestamp + ); + + expectedUserData.scaledATokenBalance = userDataBeforeAction.scaledATokenBalance; + + expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountBorrowed); + + return expectedUserData; +}; + +export const calcExpectedUserDataAfterRepay = ( + totalRepaid: string, + rateMode: RateMode, + reserveDataBeforeAction: ReserveData, + expectedDataAfterAction: ReserveData, + userDataBeforeAction: UserReserveData, + user: string, + onBehalfOf: string, + txTimestamp: BigNumber, + currentTimestamp: BigNumber +): UserReserveData => { + const expectedUserData = {}; + + const variableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + currentTimestamp + ); + + const stableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + currentTimestamp + ); + + let totalRepaidBN = new BigNumber(totalRepaid); + if (totalRepaidBN.abs().eq(MAX_UINT_AMOUNT)) { + totalRepaidBN = rateMode == RateMode.Stable ? stableDebt : variableDebt; + } + + if (rateMode == RateMode.Stable) { + expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt; + expectedUserData.currentVariableDebt = variableDebt; + + expectedUserData.principalStableDebt = expectedUserData.currentStableDebt = stableDebt.minus( + totalRepaidBN + ); + + if (expectedUserData.currentStableDebt.eq('0')) { + //user repaid everything + expectedUserData.stableBorrowRate = expectedUserData.stableRateLastUpdated = new BigNumber( + '0' + ); + } else { + expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; + expectedUserData.stableRateLastUpdated = txTimestamp; + } + } else { + expectedUserData.currentStableDebt = userDataBeforeAction.principalStableDebt; + expectedUserData.principalStableDebt = stableDebt; + expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; + expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated; + + expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt.minus( + totalRepaidBN.rayDiv(expectedDataAfterAction.variableBorrowIndex) + ); + expectedUserData.currentVariableDebt = expectedUserData.scaledVariableDebt.rayMul( + expectedDataAfterAction.variableBorrowIndex + ); + } + + expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; + + expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled; + + expectedUserData.currentATokenBalance = calcExpectedATokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + expectedUserData.scaledATokenBalance = userDataBeforeAction.scaledATokenBalance; + + if (user === onBehalfOf) { + expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(totalRepaidBN); + } else { + //wallet balance didn't change + expectedUserData.walletBalance = userDataBeforeAction.walletBalance; + } + + return expectedUserData; +}; + +export const calcExpectedUserDataAfterSetUseAsCollateral = ( + useAsCollateral: boolean, + reserveDataBeforeAction: ReserveData, + userDataBeforeAction: UserReserveData, + txCost: BigNumber +): UserReserveData => { + const expectedUserData = { ...userDataBeforeAction }; + + expectedUserData.usageAsCollateralEnabled = useAsCollateral; + + return expectedUserData; +}; + +export const calcExpectedReserveDataAfterSwapRateMode = ( + reserveDataBeforeAction: ReserveData, + userDataBeforeAction: UserReserveData, + rateMode: string, + txTimestamp: BigNumber +): ReserveData => { + const expectedReserveData: ReserveData = {}; + + expectedReserveData.address = reserveDataBeforeAction.address; + + const variableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + const stableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity; + + const totalStableDebtUntilTx = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + + if (rateMode === RateMode.Stable) { + //swap user stable debt to variable + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.plus( + stableDebt.rayDiv(expectedReserveData.variableBorrowIndex) + ); + + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = totalStableDebtUntilTx.minus( + stableDebt + ); + + expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( + reserveDataBeforeAction.averageStableBorrowRate, + expectedReserveData.principalStableDebt.plus(stableDebt), + stableDebt.negated(), + userDataBeforeAction.stableBorrowRate + ); + } else { + //swap variable to stable + + expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = totalStableDebtUntilTx.plus( + variableDebt + ); + + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.minus( + variableDebt.rayDiv(expectedReserveData.variableBorrowIndex) + ); + + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebt, + variableDebt, + reserveDataBeforeAction.stableBorrowRate + ); + } + + expectedReserveData.totalLiquidity = reserveDataBeforeAction.availableLiquidity + .plus(expectedReserveData.totalStableDebt) + .plus(expectedReserveData.totalVariableDebt); + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + + const rates = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + expectedReserveData.utilizationRate, + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.averageStableBorrowRate + ); + expectedReserveData.liquidityRate = rates[0]; + + expectedReserveData.stableBorrowRate = rates[1]; + + expectedReserveData.variableBorrowRate = rates[2]; + + return expectedReserveData; +}; + +export const calcExpectedUserDataAfterSwapRateMode = ( + reserveDataBeforeAction: ReserveData, + expectedDataAfterAction: ReserveData, + userDataBeforeAction: UserReserveData, + rateMode: string, + txCost: BigNumber, + txTimestamp: BigNumber +): UserReserveData => { + const expectedUserData = { ...userDataBeforeAction }; + + const stableDebtBalance = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + const variableDebtBalance = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + expectedUserData.currentATokenBalance = calcExpectedATokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + if (rateMode === RateMode.Stable) { + // swap to variable + expectedUserData.currentStableDebt = expectedUserData.principalStableDebt = new BigNumber(0); + + expectedUserData.stableBorrowRate = new BigNumber(0); + + expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt.plus( + stableDebtBalance.rayDiv(expectedDataAfterAction.variableBorrowIndex) + ); + expectedUserData.currentVariableDebt = expectedUserData.scaledVariableDebt.rayMul( + expectedDataAfterAction.variableBorrowIndex + ); + + expectedUserData.stableRateLastUpdated = new BigNumber(0); + } else { + expectedUserData.principalStableDebt = expectedUserData.currentStableDebt = userDataBeforeAction.currentStableDebt.plus( + variableDebtBalance + ); + + //weighted average of the previous and the current + expectedUserData.stableBorrowRate = calcExpectedUserStableRate( + stableDebtBalance, + userDataBeforeAction.stableBorrowRate, + variableDebtBalance, + reserveDataBeforeAction.stableBorrowRate + ); + + expectedUserData.stableRateLastUpdated = txTimestamp; + + expectedUserData.currentVariableDebt = expectedUserData.scaledVariableDebt = new BigNumber(0); + } + + expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; + + return expectedUserData; +}; + +export const calcExpectedReserveDataAfterStableRateRebalance = ( + reserveDataBeforeAction: ReserveData, + userDataBeforeAction: UserReserveData, + txTimestamp: BigNumber +): ReserveData => { + const expectedReserveData: ReserveData = {}; + + expectedReserveData.address = reserveDataBeforeAction.address; + + const userStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( + reserveDataBeforeAction, + txTimestamp + ); + + expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; + expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( + expectedReserveData.variableBorrowIndex + ); + + expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( + reserveDataBeforeAction.principalStableDebt, + reserveDataBeforeAction.averageStableBorrowRate, + reserveDataBeforeAction.totalStableDebtLastUpdated, + txTimestamp + ); + + expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity; + + expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity + .plus(expectedReserveData.totalStableDebt) + .plus(expectedReserveData.totalVariableDebt); + + //removing the stable liquidity at the old rate + + const avgRateBefore = calcExpectedAverageStableBorrowRateRebalance( + reserveDataBeforeAction.averageStableBorrowRate, + expectedReserveData.totalStableDebt, + userStableDebt.negated(), + userDataBeforeAction.stableBorrowRate + ); + // adding it again at the new rate + + expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRateRebalance( + avgRateBefore, + expectedReserveData.totalStableDebt.minus(userStableDebt), + userStableDebt, + reserveDataBeforeAction.stableBorrowRate + ); + + expectedReserveData.utilizationRate = calcExpectedUtilizationRate( + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.totalLiquidity + ); + + const rates = calcExpectedInterestRates( + reserveDataBeforeAction.symbol, + reserveDataBeforeAction.marketStableRate, + expectedReserveData.utilizationRate, + expectedReserveData.totalStableDebt, + expectedReserveData.totalVariableDebt, + expectedReserveData.averageStableBorrowRate + ); + + expectedReserveData.liquidityRate = rates[0]; + + expectedReserveData.stableBorrowRate = rates[1]; + + expectedReserveData.variableBorrowRate = rates[2]; + + return expectedReserveData; +}; + +export const calcExpectedUserDataAfterStableRateRebalance = ( + reserveDataBeforeAction: ReserveData, + expectedDataAfterAction: ReserveData, + userDataBeforeAction: UserReserveData, + txCost: BigNumber, + txTimestamp: BigNumber +): UserReserveData => { + const expectedUserData = { ...userDataBeforeAction }; + + expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; + + expectedUserData.principalVariableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + expectedUserData.currentStableDebt = expectedUserData.principalStableDebt = calcExpectedStableDebtTokenBalance( + userDataBeforeAction.principalStableDebt, + userDataBeforeAction.stableBorrowRate, + userDataBeforeAction.stableRateLastUpdated, + txTimestamp + ); + + expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + expectedUserData.stableRateLastUpdated = txTimestamp; + + expectedUserData.principalVariableDebt = userDataBeforeAction.principalVariableDebt; + + // Stable rate after burn + expectedUserData.stableBorrowRate = expectedDataAfterAction.averageStableBorrowRate; + expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; + + expectedUserData.currentATokenBalance = calcExpectedATokenBalance( + reserveDataBeforeAction, + userDataBeforeAction, + txTimestamp + ); + + return expectedUserData; +}; + +const calcExpectedScaledATokenBalance = ( + userDataBeforeAction: UserReserveData, + index: BigNumber, + amountAdded: BigNumber, + amountTaken: BigNumber +) => { + return userDataBeforeAction.scaledATokenBalance + .plus(amountAdded.rayDiv(index)) + .minus(amountTaken.rayDiv(index)); +}; + +export const calcExpectedATokenBalance = ( + reserveData: ReserveData, + userData: UserReserveData, + currentTimestamp: BigNumber +) => { + const index = calcExpectedReserveNormalizedIncome(reserveData, currentTimestamp); + + const { scaledATokenBalance: scaledBalanceBeforeAction } = userData; + + return scaledBalanceBeforeAction.rayMul(index); +}; + +const calcExpectedAverageStableBorrowRate = ( + avgStableRateBefore: BigNumber, + totalStableDebtBefore: BigNumber, + amountChanged: string | BigNumber, + rate: BigNumber +) => { + const weightedTotalBorrows = avgStableRateBefore.multipliedBy(totalStableDebtBefore); + const weightedAmountBorrowed = rate.multipliedBy(amountChanged); + const totalBorrowedStable = totalStableDebtBefore.plus(amountChanged); + + if (totalBorrowedStable.eq(0)) return new BigNumber('0'); + + return weightedTotalBorrows + .plus(weightedAmountBorrowed) + .div(totalBorrowedStable) + .decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +const calcExpectedAverageStableBorrowRateRebalance = ( + avgStableRateBefore: BigNumber, + totalStableDebtBefore: BigNumber, + amountChanged: BigNumber, + rate: BigNumber +) => { + const weightedTotalBorrows = avgStableRateBefore.rayMul(totalStableDebtBefore); + const weightedAmountBorrowed = rate.rayMul(amountChanged.wadToRay()); + const totalBorrowedStable = totalStableDebtBefore.plus(amountChanged.wadToRay()); + + if (totalBorrowedStable.eq(0)) return new BigNumber('0'); + + return weightedTotalBorrows + .plus(weightedAmountBorrowed) + .rayDiv(totalBorrowedStable) + .decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +export const calcExpectedVariableDebtTokenBalance = ( + reserveData: ReserveData, + userData: UserReserveData, + currentTimestamp: BigNumber +) => { + const normalizedDebt = calcExpectedReserveNormalizedDebt( + reserveData.variableBorrowRate, + reserveData.variableBorrowIndex, + reserveData.lastUpdateTimestamp, + currentTimestamp + ); + + const { scaledVariableDebt } = userData; + + return scaledVariableDebt.rayMul(normalizedDebt); +}; + +export const calcExpectedStableDebtTokenBalance = ( + principalStableDebt: BigNumber, + stableBorrowRate: BigNumber, + stableRateLastUpdated: BigNumber, + currentTimestamp: BigNumber +) => { + if ( + stableBorrowRate.eq(0) || + currentTimestamp.eq(stableRateLastUpdated) || + stableRateLastUpdated.eq(0) + ) { + return principalStableDebt; + } + + const cumulatedInterest = calcCompoundedInterest( + stableBorrowRate, + currentTimestamp, + stableRateLastUpdated + ); + + return principalStableDebt.rayMul(cumulatedInterest); +}; + +const calcLinearInterest = ( + rate: BigNumber, + currentTimestamp: BigNumber, + lastUpdateTimestamp: BigNumber +) => { + const timeDifference = currentTimestamp.minus(lastUpdateTimestamp); + + const cumulatedInterest = rate + .multipliedBy(timeDifference) + .dividedBy(new BigNumber(ONE_YEAR)) + .plus(RAY); + + return cumulatedInterest; +}; + +const calcCompoundedInterest = ( + rate: BigNumber, + currentTimestamp: BigNumber, + lastUpdateTimestamp: BigNumber +) => { + const timeDifference = currentTimestamp.minus(lastUpdateTimestamp); + + if (timeDifference.eq(0)) { + return new BigNumber(RAY); + } + + const expMinusOne = timeDifference.minus(1); + const expMinusTwo = timeDifference.gt(2) ? timeDifference.minus(2) : 0; + + const ratePerSecond = rate.div(ONE_YEAR); + + const basePowerTwo = ratePerSecond.rayMul(ratePerSecond); + const basePowerThree = basePowerTwo.rayMul(ratePerSecond); + + const secondTerm = timeDifference.times(expMinusOne).times(basePowerTwo).div(2); + const thirdTerm = timeDifference + .times(expMinusOne) + .times(expMinusTwo) + .times(basePowerThree) + .div(6); + + return new BigNumber(RAY) + .plus(ratePerSecond.times(timeDifference)) + .plus(secondTerm) + .plus(thirdTerm); +}; + +export const calcExpectedInterestRates = ( + reserveSymbol: string, + marketStableRate: BigNumber, + utilizationRate: BigNumber, + totalStableDebt: BigNumber, + totalVariableDebt: BigNumber, + averageStableBorrowRate: BigNumber +): BigNumber[] => { + const { reservesParams } = configuration; + + const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol); + const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[ + reserveIndex + ]; + + let stableBorrowRate: BigNumber = marketStableRate; + let variableBorrowRate: BigNumber = new BigNumber(reserveConfiguration.baseVariableBorrowRate); + + const optimalRate = new BigNumber(reserveConfiguration.optimalUtilizationRate); + const excessRate = new BigNumber(RAY).minus(optimalRate); + if (utilizationRate.gt(optimalRate)) { + const excessUtilizationRateRatio = utilizationRate + .minus(reserveConfiguration.optimalUtilizationRate) + .rayDiv(excessRate); + + stableBorrowRate = stableBorrowRate + .plus(reserveConfiguration.stableRateSlope1) + .plus( + new BigNumber(reserveConfiguration.stableRateSlope2).rayMul(excessUtilizationRateRatio) + ); + + variableBorrowRate = variableBorrowRate + .plus(reserveConfiguration.variableRateSlope1) + .plus( + new BigNumber(reserveConfiguration.variableRateSlope2).rayMul(excessUtilizationRateRatio) + ); + } else { + stableBorrowRate = stableBorrowRate.plus( + new BigNumber(reserveConfiguration.stableRateSlope1).rayMul( + utilizationRate.rayDiv(new BigNumber(optimalRate)) + ) + ); + + variableBorrowRate = variableBorrowRate.plus( + utilizationRate + .rayDiv(optimalRate) + .rayMul(new BigNumber(reserveConfiguration.variableRateSlope1)) + ); + } + + const expectedOverallRate = calcExpectedOverallBorrowRate( + totalStableDebt, + totalVariableDebt, + variableBorrowRate, + averageStableBorrowRate + ); + const liquidityRate = expectedOverallRate + .rayMul(utilizationRate) + .percentMul(new BigNumber(PERCENTAGE_FACTOR).minus(reserveConfiguration.reserveFactor)); + + return [liquidityRate, stableBorrowRate, variableBorrowRate]; +}; + +export const calcExpectedOverallBorrowRate = ( + totalStableDebt: BigNumber, + totalVariableDebt: BigNumber, + currentVariableBorrowRate: BigNumber, + currentAverageStableBorrowRate: BigNumber +): BigNumber => { + const totalBorrows = totalStableDebt.plus(totalVariableDebt); + + if (totalBorrows.eq(0)) return strToBN('0'); + + const weightedVariableRate = totalVariableDebt.wadToRay().rayMul(currentVariableBorrowRate); + + const weightedStableRate = totalStableDebt.wadToRay().rayMul(currentAverageStableBorrowRate); + + const overallBorrowRate = weightedVariableRate + .plus(weightedStableRate) + .rayDiv(totalBorrows.wadToRay()); + + return overallBorrowRate; +}; + +export const calcExpectedUtilizationRate = ( + totalStableDebt: BigNumber, + totalVariableDebt: BigNumber, + totalLiquidity: BigNumber +): BigNumber => { + if (totalStableDebt.eq('0') && totalVariableDebt.eq('0')) { + return strToBN('0'); + } + + const utilization = totalStableDebt.plus(totalVariableDebt).rayDiv(totalLiquidity); + + return utilization; +}; + +const calcExpectedReserveNormalizedIncome = ( + reserveData: ReserveData, + currentTimestamp: BigNumber +) => { + const { liquidityRate, liquidityIndex, lastUpdateTimestamp } = reserveData; + + //if utilization rate is 0, nothing to compound + if (liquidityRate.eq('0')) { + return liquidityIndex; + } + + const cumulatedInterest = calcLinearInterest( + liquidityRate, + currentTimestamp, + lastUpdateTimestamp + ); + + const income = cumulatedInterest.rayMul(liquidityIndex); + + return income; +}; + +const calcExpectedReserveNormalizedDebt = ( + variableBorrowRate: BigNumber, + variableBorrowIndex: BigNumber, + lastUpdateTimestamp: BigNumber, + currentTimestamp: BigNumber +) => { + //if utilization rate is 0, nothing to compound + if (variableBorrowRate.eq('0')) { + return variableBorrowIndex; + } + + const cumulatedInterest = calcCompoundedInterest( + variableBorrowRate, + currentTimestamp, + lastUpdateTimestamp + ); + + const debt = cumulatedInterest.rayMul(variableBorrowIndex); + + return debt; +}; + +const calcExpectedUserStableRate = ( + balanceBefore: BigNumber, + rateBefore: BigNumber, + amount: BigNumber, + rateNew: BigNumber +) => { + return balanceBefore + .times(rateBefore) + .plus(amount.times(rateNew)) + .div(balanceBefore.plus(amount)); +}; + +const calcExpectedLiquidityIndex = (reserveData: ReserveData, timestamp: BigNumber) => { + //if utilization rate is 0, nothing to compound + if (reserveData.utilizationRate.eq('0')) { + return reserveData.liquidityIndex; + } + + const cumulatedInterest = calcLinearInterest( + reserveData.liquidityRate, + timestamp, + reserveData.lastUpdateTimestamp + ); + + return cumulatedInterest.rayMul(reserveData.liquidityIndex); +}; + +const calcExpectedVariableBorrowIndex = (reserveData: ReserveData, timestamp: BigNumber) => { + //if totalVariableDebt is 0, nothing to compound + if (reserveData.totalVariableDebt.eq('0')) { + return reserveData.variableBorrowIndex; + } + + const cumulatedInterest = calcCompoundedInterest( + reserveData.variableBorrowRate, + timestamp, + reserveData.lastUpdateTimestamp + ); + + return cumulatedInterest.rayMul(reserveData.variableBorrowIndex); +}; + +const calcExpectedTotalStableDebt = ( + principalStableDebt: BigNumber, + averageStableBorrowRate: BigNumber, + lastUpdateTimestamp: BigNumber, + currentTimestamp: BigNumber +) => { + const cumulatedInterest = calcCompoundedInterest( + averageStableBorrowRate, + currentTimestamp, + lastUpdateTimestamp + ); + + return cumulatedInterest.rayMul(principalStableDebt); +}; + +const calcExpectedTotalVariableDebt = ( + reserveData: ReserveData, + expectedVariableDebtIndex: BigNumber +) => { + return reserveData.scaledVariableDebt.rayMul(expectedVariableDebtIndex); +}; diff --git a/test-suites/test-lp/helpers/utils/helpers.ts b/test-suites/test-lp/helpers/utils/helpers.ts new file mode 100644 index 00000000..a1a1a82a --- /dev/null +++ b/test-suites/test-lp/helpers/utils/helpers.ts @@ -0,0 +1,129 @@ +import { LendingPool } from '../../../../types/LendingPool'; +import { ReserveData, UserReserveData } from './interfaces'; +import { + getLendingRateOracle, + getIErc20Detailed, + getMintableERC20, + getAToken, + getStableDebtToken, + getVariableDebtToken, +} from '../../../../helpers/contracts-getters'; +import { tEthereumAddress } from '../../../../helpers/types'; +import BigNumber from 'bignumber.js'; +import { getDb, DRE } from '../../../../helpers/misc-utils'; +import { AaveProtocolDataProvider } from '../../../../types/AaveProtocolDataProvider'; + +export const getReserveData = async ( + helper: AaveProtocolDataProvider, + reserve: tEthereumAddress +): Promise => { + const [reserveData, tokenAddresses, rateOracle, token] = await Promise.all([ + helper.getReserveData(reserve), + helper.getReserveTokensAddresses(reserve), + getLendingRateOracle(), + getIErc20Detailed(reserve), + ]); + + const stableDebtToken = await getStableDebtToken(tokenAddresses.stableDebtTokenAddress); + const variableDebtToken = await getVariableDebtToken(tokenAddresses.variableDebtTokenAddress); + + const { 0: principalStableDebt } = await stableDebtToken.getSupplyData(); + const totalStableDebtLastUpdated = await stableDebtToken.getTotalSupplyLastUpdated(); + + const scaledVariableDebt = await variableDebtToken.scaledTotalSupply(); + + const rate = (await rateOracle.getMarketBorrowRate(reserve)).toString(); + const symbol = await token.symbol(); + const decimals = new BigNumber(await token.decimals()); + + const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) + .plus(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()); + + const utilizationRate = new BigNumber( + totalLiquidity.eq(0) + ? 0 + : new BigNumber(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()) + .rayDiv(totalLiquidity) + ); + + return { + totalLiquidity, + utilizationRate, + availableLiquidity: new BigNumber(reserveData.availableLiquidity.toString()), + totalStableDebt: new BigNumber(reserveData.totalStableDebt.toString()), + totalVariableDebt: new BigNumber(reserveData.totalVariableDebt.toString()), + liquidityRate: new BigNumber(reserveData.liquidityRate.toString()), + variableBorrowRate: new BigNumber(reserveData.variableBorrowRate.toString()), + stableBorrowRate: new BigNumber(reserveData.stableBorrowRate.toString()), + averageStableBorrowRate: new BigNumber(reserveData.averageStableBorrowRate.toString()), + liquidityIndex: new BigNumber(reserveData.liquidityIndex.toString()), + variableBorrowIndex: new BigNumber(reserveData.variableBorrowIndex.toString()), + lastUpdateTimestamp: new BigNumber(reserveData.lastUpdateTimestamp), + totalStableDebtLastUpdated: new BigNumber(totalStableDebtLastUpdated), + principalStableDebt: new BigNumber(principalStableDebt.toString()), + scaledVariableDebt: new BigNumber(scaledVariableDebt.toString()), + address: reserve, + aTokenAddress: tokenAddresses.aTokenAddress, + symbol, + decimals, + marketStableRate: new BigNumber(rate), + }; +}; + +export const getUserData = async ( + pool: LendingPool, + helper: AaveProtocolDataProvider, + reserve: string, + user: tEthereumAddress, + sender?: tEthereumAddress +): Promise => { + const [userData, scaledATokenBalance] = await Promise.all([ + helper.getUserReserveData(reserve, user), + getATokenUserData(reserve, user, helper), + ]); + + const token = await getMintableERC20(reserve); + const walletBalance = new BigNumber((await token.balanceOf(sender || user)).toString()); + + return { + scaledATokenBalance: new BigNumber(scaledATokenBalance), + currentATokenBalance: new BigNumber(userData.currentATokenBalance.toString()), + currentStableDebt: new BigNumber(userData.currentStableDebt.toString()), + currentVariableDebt: new BigNumber(userData.currentVariableDebt.toString()), + principalStableDebt: new BigNumber(userData.principalStableDebt.toString()), + scaledVariableDebt: new BigNumber(userData.scaledVariableDebt.toString()), + stableBorrowRate: new BigNumber(userData.stableBorrowRate.toString()), + liquidityRate: new BigNumber(userData.liquidityRate.toString()), + usageAsCollateralEnabled: userData.usageAsCollateralEnabled, + stableRateLastUpdated: new BigNumber(userData.stableRateLastUpdated.toString()), + walletBalance, + }; +}; + +export const getReserveAddressFromSymbol = async (symbol: string) => { + + const token = await getMintableERC20( + (await getDb().get(`${symbol}.${DRE.network.name}`).value()).address + ); + + if (!token) { + throw `Could not find instance for contract ${symbol}`; + } + return token.address; +}; + +const getATokenUserData = async ( + reserve: string, + user: string, + helpersContract: AaveProtocolDataProvider +) => { + const aTokenAddress: string = (await helpersContract.getReserveTokensAddresses(reserve)) + .aTokenAddress; + + const aToken = await getAToken(aTokenAddress); + + const scaledBalance = await aToken.scaledBalanceOf(user); + return scaledBalance.toString(); +}; diff --git a/test-suites/test-lp/helpers/utils/interfaces/index.ts b/test-suites/test-lp/helpers/utils/interfaces/index.ts new file mode 100644 index 00000000..17660fcc --- /dev/null +++ b/test-suites/test-lp/helpers/utils/interfaces/index.ts @@ -0,0 +1,40 @@ +import BigNumber from 'bignumber.js'; + +export interface UserReserveData { + scaledATokenBalance: BigNumber; + currentATokenBalance: BigNumber; + currentStableDebt: BigNumber; + currentVariableDebt: BigNumber; + principalStableDebt: BigNumber; + scaledVariableDebt: BigNumber; + liquidityRate: BigNumber; + stableBorrowRate: BigNumber; + stableRateLastUpdated: BigNumber; + usageAsCollateralEnabled: Boolean; + walletBalance: BigNumber; + [key: string]: BigNumber | string | Boolean; +} + +export interface ReserveData { + address: string; + symbol: string; + decimals: BigNumber; + totalLiquidity: BigNumber; + availableLiquidity: BigNumber; + totalStableDebt: BigNumber; + totalVariableDebt: BigNumber; + principalStableDebt: BigNumber; + scaledVariableDebt: BigNumber; + averageStableBorrowRate: BigNumber; + variableBorrowRate: BigNumber; + stableBorrowRate: BigNumber; + utilizationRate: BigNumber; + liquidityIndex: BigNumber; + variableBorrowIndex: BigNumber; + aTokenAddress: string; + marketStableRate: BigNumber; + lastUpdateTimestamp: BigNumber; + totalStableDebtLastUpdated: BigNumber; + liquidityRate: BigNumber; + [key: string]: BigNumber | string; +} diff --git a/test-suites/test-lp/helpers/utils/math.ts b/test-suites/test-lp/helpers/utils/math.ts new file mode 100644 index 00000000..27ea0531 --- /dev/null +++ b/test-suites/test-lp/helpers/utils/math.ts @@ -0,0 +1,97 @@ +import BigNumber from 'bignumber.js'; +import { + RAY, + WAD, + HALF_RAY, + HALF_WAD, + WAD_RAY_RATIO, + HALF_PERCENTAGE, + PERCENTAGE_FACTOR, +} from '../../../../helpers/constants'; + +declare module 'bignumber.js' { + interface BigNumber { + ray: () => BigNumber; + wad: () => BigNumber; + halfRay: () => BigNumber; + halfWad: () => BigNumber; + halfPercentage: () => BigNumber; + wadMul: (a: BigNumber) => BigNumber; + wadDiv: (a: BigNumber) => BigNumber; + rayMul: (a: BigNumber) => BigNumber; + rayDiv: (a: BigNumber) => BigNumber; + percentMul: (a: BigNumber) => BigNumber; + percentDiv: (a: BigNumber) => BigNumber; + rayToWad: () => BigNumber; + wadToRay: () => BigNumber; + } +} + +BigNumber.prototype.ray = (): BigNumber => { + return new BigNumber(RAY).decimalPlaces(0); +}; +BigNumber.prototype.wad = (): BigNumber => { + return new BigNumber(WAD).decimalPlaces(0); +}; + +BigNumber.prototype.halfRay = (): BigNumber => { + return new BigNumber(HALF_RAY).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.halfWad = (): BigNumber => { + return new BigNumber(HALF_WAD).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.wadMul = function (b: BigNumber): BigNumber { + return this.halfWad().plus(this.multipliedBy(b)).div(WAD).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.wadDiv = function (a: BigNumber): BigNumber { + const halfA = a.div(2).decimalPlaces(0, BigNumber.ROUND_DOWN); + + return halfA.plus(this.multipliedBy(WAD)).div(a).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.rayMul = function (a: BigNumber): BigNumber { + return this.halfRay().plus(this.multipliedBy(a)).div(RAY).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.rayDiv = function (a: BigNumber): BigNumber { + const halfA = a.div(2).decimalPlaces(0, BigNumber.ROUND_DOWN); + + return halfA + .plus(this.multipliedBy(RAY)) + .decimalPlaces(0, BigNumber.ROUND_DOWN) + .div(a) + .decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.rayToWad = function (): BigNumber { + const halfRatio = new BigNumber(WAD_RAY_RATIO).div(2); + + return halfRatio.plus(this).div(WAD_RAY_RATIO).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.wadToRay = function (): BigNumber { + return this.multipliedBy(WAD_RAY_RATIO).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.halfPercentage = (): BigNumber => { + return new BigNumber(HALF_PERCENTAGE).decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.percentMul = function (b: BigNumber): BigNumber { + return this.halfPercentage() + .plus(this.multipliedBy(b)) + .div(PERCENTAGE_FACTOR) + .decimalPlaces(0, BigNumber.ROUND_DOWN); +}; + +BigNumber.prototype.percentDiv = function (a: BigNumber): BigNumber { + const halfA = a.div(2).decimalPlaces(0, BigNumber.ROUND_DOWN); + + return halfA + .plus(this.multipliedBy(PERCENTAGE_FACTOR)) + .div(a) + .decimalPlaces(0, BigNumber.ROUND_DOWN); +}; diff --git a/test-suites/test-lp/lending-pool-addresses-provider.spec.ts b/test-suites/test-lp/lending-pool-addresses-provider.spec.ts new file mode 100644 index 00000000..0f7630f9 --- /dev/null +++ b/test-suites/test-lp/lending-pool-addresses-provider.spec.ts @@ -0,0 +1,101 @@ +import { expect } from 'chai'; +import { createRandomAddress } from '../../helpers/misc-utils'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +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-deployments'; + +const { utils } = ethers; + +makeSuite('LendingPoolAddressesProvider', (testEnv: TestEnv) => { + it('Test the accessibility of the LendingPoolAddressesProvider', async () => { + const { addressesProvider, users } = testEnv; + const mockAddress = createRandomAddress(); + const { INVALID_OWNER_REVERT_MSG } = ProtocolErrors; + + await addressesProvider.transferOwnership(users[1].address); + + for (const contractFunction of [ + addressesProvider.setMarketId, + addressesProvider.setLendingPoolImpl, + addressesProvider.setLendingPoolConfiguratorImpl, + addressesProvider.setLendingPoolCollateralManager, + addressesProvider.setPoolAdmin, + addressesProvider.setPriceOracle, + addressesProvider.setLendingRateOracle, + ]) { + await expect(contractFunction(mockAddress)).to.be.revertedWith(INVALID_OWNER_REVERT_MSG); + } + + await expect( + addressesProvider.setAddress(utils.keccak256(utils.toUtf8Bytes('RANDOM_ID')), mockAddress) + ).to.be.revertedWith(INVALID_OWNER_REVERT_MSG); + + await expect( + addressesProvider.setAddressAsProxy( + utils.keccak256(utils.toUtf8Bytes('RANDOM_ID')), + mockAddress + ) + ).to.be.revertedWith(INVALID_OWNER_REVERT_MSG); + }); + + it('Tests adding a proxied address with `setAddressAsProxy()`', async () => { + const { addressesProvider, users } = testEnv; + const { INVALID_OWNER_REVERT_MSG } = ProtocolErrors; + + const currentAddressesProviderOwner = users[1]; + + const mockLendingPool = await deployLendingPool(); + const proxiedAddressId = utils.keccak256(utils.toUtf8Bytes('RANDOM_PROXIED')); + + const proxiedAddressSetReceipt = await waitForTx( + await addressesProvider + .connect(currentAddressesProviderOwner.signer) + .setAddressAsProxy(proxiedAddressId, mockLendingPool.address) + ); + + if (!proxiedAddressSetReceipt.events || proxiedAddressSetReceipt.events?.length < 1) { + throw new Error('INVALID_EVENT_EMMITED'); + } + + expect(proxiedAddressSetReceipt.events[0].event).to.be.equal('ProxyCreated'); + expect(proxiedAddressSetReceipt.events[1].event).to.be.equal('AddressSet'); + expect(proxiedAddressSetReceipt.events[1].args?.id).to.be.equal(proxiedAddressId); + expect(proxiedAddressSetReceipt.events[1].args?.newAddress).to.be.equal( + mockLendingPool.address + ); + expect(proxiedAddressSetReceipt.events[1].args?.hasProxy).to.be.equal(true); + }); + + it('Tests adding a non proxied address with `setAddress()`', async () => { + const { addressesProvider, users } = testEnv; + const { INVALID_OWNER_REVERT_MSG } = ProtocolErrors; + + const currentAddressesProviderOwner = users[1]; + const mockNonProxiedAddress = createRandomAddress(); + const nonProxiedAddressId = utils.keccak256(utils.toUtf8Bytes('RANDOM_NON_PROXIED')); + + const nonProxiedAddressSetReceipt = await waitForTx( + await addressesProvider + .connect(currentAddressesProviderOwner.signer) + .setAddress(nonProxiedAddressId, mockNonProxiedAddress) + ); + + expect(mockNonProxiedAddress.toLowerCase()).to.be.equal( + (await addressesProvider.getAddress(nonProxiedAddressId)).toLowerCase() + ); + + if (!nonProxiedAddressSetReceipt.events || nonProxiedAddressSetReceipt.events?.length < 1) { + throw new Error('INVALID_EVENT_EMMITED'); + } + + expect(nonProxiedAddressSetReceipt.events[0].event).to.be.equal('AddressSet'); + expect(nonProxiedAddressSetReceipt.events[0].args?.id).to.be.equal(nonProxiedAddressId); + expect(nonProxiedAddressSetReceipt.events[0].args?.newAddress).to.be.equal( + mockNonProxiedAddress + ); + expect(nonProxiedAddressSetReceipt.events[0].args?.hasProxy).to.be.equal(false); + }); +}); diff --git a/test-suites/test-lp/liquidation-atoken.spec.ts b/test-suites/test-lp/liquidation-atoken.spec.ts new file mode 100644 index 00000000..1b6f9911 --- /dev/null +++ b/test-suites/test-lp/liquidation-atoken.spec.ts @@ -0,0 +1,379 @@ +import BigNumber from 'bignumber.js'; + +import { DRE } from '../../helpers/misc-utils'; +import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { makeSuite } from './helpers/make-suite'; +import { ProtocolErrors, RateMode } from '../../helpers/types'; +import { calcExpectedVariableDebtTokenBalance } from './helpers/utils/calculations'; +import { getUserData, getReserveData } from './helpers/utils/helpers'; + +const chai = require('chai'); +const { expect } = chai; + +makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) => { + const { + LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD, + INVALID_HF, + LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER, + LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED, + LP_IS_PAUSED, + } = ProtocolErrors; + + it('Deposits WETH, borrows DAI/Check liquidation fails because health factor is above 1', async () => { + const { dai, weth, users, pool, oracle } = testEnv; + const depositor = users[0]; + const borrower = users[1]; + + //mints DAI to depositor + await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access depositor wallet + await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 1 deposits 1000 DAI + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + await pool + .connect(depositor.signer) + .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); + + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(amountETHtoDeposit); + + //approve protocol to access borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 2 deposits 1 WETH + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 2 borrows + const userGlobalData = await pool.getUserAccountData(borrower.address); + const daiPrice = await oracle.getAssetPrice(dai.address); + + const amountDAIToBorrow = await convertToCurrencyDecimals( + dai.address, + new BigNumber(userGlobalData.availableBorrowsETH.toString()) + .div(daiPrice.toString()) + .multipliedBy(0.95) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(dai.address, amountDAIToBorrow, RateMode.Variable, '0', borrower.address); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.bignumber.equal( + '8250', + 'Invalid liquidation threshold' + ); + + //someone tries to liquidate user 2 + await expect( + pool.liquidationCall(weth.address, dai.address, borrower.address, 1, true) + ).to.be.revertedWith(LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD); + }); + + it('Drop the health factor below 1', async () => { + const { dai, users, pool, oracle } = testEnv; + const borrower = users[1]; + + const daiPrice = await oracle.getAssetPrice(dai.address); + + await oracle.setAssetPrice( + dai.address, + new BigNumber(daiPrice.toString()).multipliedBy(1.15).toFixed(0) + ); + + const userGlobalData = await pool.getUserAccountData(borrower.address); + + expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( + oneEther.toString(), + INVALID_HF + ); + }); + + it('Tries to liquidate a different currency than the loan principal', async () => { + const { pool, users, weth } = testEnv; + const borrower = users[1]; + //user 2 tries to borrow + await expect( + pool.liquidationCall(weth.address, weth.address, borrower.address, oneEther.toString(), true) + ).revertedWith(LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER); + }); + + it('Tries to liquidate a different collateral than the borrower collateral', async () => { + const { pool, dai, users } = testEnv; + const borrower = users[1]; + + await expect( + pool.liquidationCall(dai.address, dai.address, borrower.address, oneEther.toString(), true) + ).revertedWith(LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED); + }); + + it('Liquidates the borrow', async () => { + const { pool, dai, weth, aWETH, aDai, users, oracle, helpersContract, deployer } = testEnv; + const borrower = users[1]; + + //mints dai to the caller + + await dai.mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access depositor wallet + await dai.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const daiReserveDataBefore = await getReserveData(helpersContract, dai.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const amountToLiquidate = new BigNumber(userReserveDataBefore.currentVariableDebt.toString()) + .div(2) + .toFixed(0); + + const tx = await pool.liquidationCall( + weth.address, + dai.address, + borrower.address, + amountToLiquidate, + true + ); + + const userReserveDataAfter = await helpersContract.getUserReserveData( + dai.address, + borrower.address + ); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); + const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + + const collateralPrice = (await oracle.getAssetPrice(weth.address)).toString(); + const principalPrice = (await oracle.getAssetPrice(dai.address)).toString(); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(dai.address) + ).decimals.toString(); + + const expectedCollateralLiquidated = new BigNumber(principalPrice) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals))) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + if (!tx.blockNumber) { + expect(false, 'Invalid block number'); + return; + } + + const txTimestamp = new BigNumber( + (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp + ); + + const variableDebtBeforeTx = calcExpectedVariableDebtTokenBalance( + daiReserveDataBefore, + userReserveDataBefore, + txTimestamp + ); + + expect(userGlobalDataAfter.healthFactor.toString()).to.be.bignumber.gt( + oneEther.toFixed(0), + 'Invalid health factor' + ); + + expect(userReserveDataAfter.currentVariableDebt.toString()).to.be.bignumber.almostEqual( + new BigNumber(variableDebtBeforeTx).minus(amountToLiquidate).toFixed(0), + 'Invalid user borrow balance after liquidation' + ); + + expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(daiReserveDataBefore.availableLiquidity.toString()) + .plus(amountToLiquidate) + .toFixed(0), + 'Invalid principal available liquidity' + ); + + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( + daiReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + daiReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + + expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(ethReserveDataBefore.availableLiquidity.toString()).toFixed(0), + 'Invalid collateral available liquidity' + ); + + expect( + (await helpersContract.getUserReserveData(weth.address, deployer.address)) + .usageAsCollateralEnabled + ).to.be.true; + }); + + it('User 3 deposits 1000 USDC, user 4 1 WETH, user 4 borrows - drops HF, liquidates the borrow', async () => { + const { users, pool, usdc, oracle, weth, helpersContract } = testEnv; + const depositor = users[3]; + const borrower = users[4]; + + //mints USDC to depositor + await usdc + .connect(depositor.signer) + .mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 3 deposits 1000 USDC + const amountUSDCtoDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(usdc.address, amountUSDCtoDeposit, depositor.address, '0'); + + //user 4 deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(amountETHtoDeposit); + + //approve protocol to access borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 4 borrows + const userGlobalData = await pool.getUserAccountData(borrower.address); + + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const amountUSDCToBorrow = await convertToCurrencyDecimals( + usdc.address, + new BigNumber(userGlobalData.availableBorrowsETH.toString()) + .div(usdcPrice.toString()) + .multipliedBy(0.9502) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); + + //drops HF below 1 + + await oracle.setAssetPrice( + usdc.address, + new BigNumber(usdcPrice.toString()).multipliedBy(1.12).toFixed(0) + ); + + //mints dai to the liquidator + + await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const userReserveDataBefore = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + + const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .multipliedBy(0.5) + .toFixed(0); + + await pool.liquidationCall( + weth.address, + usdc.address, + borrower.address, + amountToLiquidate, + true + ); + + const userReserveDataAfter = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + const usdcReserveDataAfter = await helpersContract.getReserveData(usdc.address); + const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + + const collateralPrice = (await oracle.getAssetPrice(weth.address)).toString(); + const principalPrice = (await oracle.getAssetPrice(usdc.address)).toString(); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(usdc.address) + ).decimals.toString(); + + const expectedCollateralLiquidated = new BigNumber(principalPrice) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals))) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + expect(userGlobalDataAfter.healthFactor.toString()).to.be.bignumber.gt( + oneEther.toFixed(0), + 'Invalid health factor' + ); + + expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( + new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .minus(amountToLiquidate) + .toFixed(0), + 'Invalid user borrow balance after liquidation' + ); + + expect(usdcReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(usdcReserveDataBefore.availableLiquidity.toString()) + .plus(amountToLiquidate) + .toFixed(0), + 'Invalid principal available liquidity' + ); + + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(usdcReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( + usdcReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(usdcReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + usdcReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + + expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(ethReserveDataBefore.availableLiquidity.toString()).toFixed(0), + 'Invalid collateral available liquidity' + ); + }); +}); diff --git a/test-suites/test-lp/liquidation-underlying.spec.ts b/test-suites/test-lp/liquidation-underlying.spec.ts new file mode 100644 index 00000000..7f557409 --- /dev/null +++ b/test-suites/test-lp/liquidation-underlying.spec.ts @@ -0,0 +1,492 @@ +import BigNumber from 'bignumber.js'; + +import { DRE, increaseTime } from '../../helpers/misc-utils'; +import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { makeSuite } from './helpers/make-suite'; +import { ProtocolErrors, RateMode } from '../../helpers/types'; +import { calcExpectedStableDebtTokenBalance } from './helpers/utils/calculations'; +import { getUserData } from './helpers/utils/helpers'; +import { CommonsConfig } from '../../markets/uniswap/commons'; + +import { parseEther } from 'ethers/lib/utils'; + +const chai = require('chai'); + +const { expect } = chai; + +makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', (testEnv) => { + const { INVALID_HF } = ProtocolErrors; + + before('Before LendingPool liquidation: set config', () => { + BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); + }); + + after('After LendingPool liquidation: reset config', () => { + BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); + }); + + it("It's not possible to liquidate on a non-active collateral or a non active principal", async () => { + const { configurator, weth, pool, users, dai } = testEnv; + const user = users[1]; + await configurator.deactivateReserve(weth.address); + + await expect( + pool.liquidationCall(weth.address, dai.address, user.address, parseEther('1000'), false) + ).to.be.revertedWith('2'); + + await configurator.activateReserve(weth.address); + + await configurator.deactivateReserve(dai.address); + + await expect( + pool.liquidationCall(weth.address, dai.address, user.address, parseEther('1000'), false) + ).to.be.revertedWith('2'); + + await configurator.activateReserve(dai.address); + }); + + it('Deposits WETH, borrows DAI', async () => { + const { dai, weth, users, pool, oracle } = testEnv; + const depositor = users[0]; + const borrower = users[1]; + + //mints DAI to depositor + await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access depositor wallet + await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 1 deposits 1000 DAI + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); + //user 2 deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); + + //approve protocol to access the borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 2 borrows + + const userGlobalData = await pool.getUserAccountData(borrower.address); + const daiPrice = await oracle.getAssetPrice(dai.address); + + const amountDAIToBorrow = await convertToCurrencyDecimals( + dai.address, + new BigNumber(userGlobalData.availableBorrowsETH.toString()) + .div(daiPrice.toString()) + .multipliedBy(0.95) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.bignumber.equal( + '8250', + INVALID_HF + ); + }); + + it('Drop the health factor below 1', async () => { + const { dai, weth, users, pool, oracle } = testEnv; + const borrower = users[1]; + + const daiPrice = await oracle.getAssetPrice(dai.address); + + await oracle.setAssetPrice( + dai.address, + new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0) + ); + + const userGlobalData = await pool.getUserAccountData(borrower.address); + + expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( + oneEther.toFixed(0), + INVALID_HF + ); + }); + + it('Liquidates the borrow', async () => { + const { dai, weth, users, pool, oracle, helpersContract } = testEnv; + const liquidator = users[3]; + const borrower = users[1]; + + //mints dai to the liquidator + await dai.connect(liquidator.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + //approve protocol to access the liquidator wallet + await dai.connect(liquidator.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + + const userReserveDataBefore = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + + await increaseTime(100); + + const tx = await pool + .connect(liquidator.signer) + .liquidationCall(weth.address, dai.address, borrower.address, amountToLiquidate, false); + + const userReserveDataAfter = await getUserData( + pool, + helpersContract, + dai.address, + borrower.address + ); + + const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); + const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + + const collateralPrice = await oracle.getAssetPrice(weth.address); + const principalPrice = await oracle.getAssetPrice(dai.address); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(dai.address) + ).decimals.toString(); + + const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div( + new BigNumber(collateralPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div(100) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + if (!tx.blockNumber) { + expect(false, 'Invalid block number'); + return; + } + const txTimestamp = new BigNumber( + (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp + ); + + const stableDebtBeforeTx = calcExpectedStableDebtTokenBalance( + userReserveDataBefore.principalStableDebt, + userReserveDataBefore.stableBorrowRate, + userReserveDataBefore.stableRateLastUpdated, + txTimestamp + ); + + expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( + stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), + 'Invalid user debt after liquidation' + ); + + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( + daiReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + daiReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + + expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(daiReserveDataBefore.availableLiquidity.toString()) + .plus(amountToLiquidate) + .toFixed(0), + 'Invalid principal available liquidity' + ); + + expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) + .minus(expectedCollateralLiquidated) + .toFixed(0), + 'Invalid collateral available liquidity' + ); + }); + + it('User 3 deposits 1000 USDC, user 4 1 WETH, user 4 borrows - drops HF, liquidates the borrow', async () => { + const { usdc, users, pool, oracle, weth, helpersContract } = testEnv; + + const depositor = users[3]; + const borrower = users[4]; + const liquidator = users[5]; + + //mints USDC to depositor + await usdc + .connect(depositor.signer) + .mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //depositor deposits 1000 USDC + const amountUSDCtoDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(usdc.address, amountUSDCtoDeposit, depositor.address, '0'); + + //borrower deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); + + //approve protocol to access the borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //borrower borrows + const userGlobalData = await pool.getUserAccountData(borrower.address); + + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const amountUSDCToBorrow = await convertToCurrencyDecimals( + usdc.address, + new BigNumber(userGlobalData.availableBorrowsETH.toString()) + .div(usdcPrice.toString()) + .multipliedBy(0.9502) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); + + //drops HF below 1 + await oracle.setAssetPrice( + usdc.address, + new BigNumber(usdcPrice.toString()).multipliedBy(1.12).toFixed(0) + ); + + //mints dai to the liquidator + + await usdc + .connect(liquidator.signer) + .mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.connect(liquidator.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const userReserveDataBefore = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address); + const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); + + const amountToLiquidate = DRE.ethers.BigNumber.from( + userReserveDataBefore.currentStableDebt.toString() + ) + .div(2) + .toString(); + + await pool + .connect(liquidator.signer) + .liquidationCall(weth.address, usdc.address, borrower.address, amountToLiquidate, false); + + const userReserveDataAfter = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + const usdcReserveDataAfter = await helpersContract.getReserveData(usdc.address); + const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + + const collateralPrice = await oracle.getAssetPrice(weth.address); + const principalPrice = await oracle.getAssetPrice(usdc.address); + + const collateralDecimals = ( + await helpersContract.getReserveConfigurationData(weth.address) + ).decimals.toString(); + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(usdc.address) + ).decimals.toString(); + + const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) + .times(new BigNumber(amountToLiquidate).times(105)) + .times(new BigNumber(10).pow(collateralDecimals)) + .div( + new BigNumber(collateralPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div(100) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + expect(userGlobalDataAfter.healthFactor.toString()).to.be.bignumber.gt( + oneEther.toFixed(0), + 'Invalid health factor' + ); + + expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( + new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .minus(amountToLiquidate) + .toFixed(0), + 'Invalid user borrow balance after liquidation' + ); + + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(usdcReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( + usdcReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(usdcReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + usdcReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + + expect(usdcReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(usdcReserveDataBefore.availableLiquidity.toString()) + .plus(amountToLiquidate) + .toFixed(0), + 'Invalid principal available liquidity' + ); + + expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) + .minus(expectedCollateralLiquidated) + .toFixed(0), + 'Invalid collateral available liquidity' + ); + }); + + it('User 4 deposits 10 AAVE - drops HF, liquidates the AAVE, which results on a lower amount being liquidated', async () => { + const { aave, usdc, users, pool, oracle, helpersContract } = testEnv; + + const depositor = users[3]; + const borrower = users[4]; + const liquidator = users[5]; + + //mints AAVE to borrower + await aave.connect(borrower.signer).mint(await convertToCurrencyDecimals(aave.address, '10')); + + //approve protocol to access the borrower wallet + await aave.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //borrower deposits 10 AAVE + const amountToDeposit = await convertToCurrencyDecimals(aave.address, '10'); + + await pool + .connect(borrower.signer) + .deposit(aave.address, amountToDeposit, borrower.address, '0'); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + //drops HF below 1 + await oracle.setAssetPrice( + usdc.address, + new BigNumber(usdcPrice.toString()).multipliedBy(1.14).toFixed(0) + ); + + //mints usdc to the liquidator + await usdc + .connect(liquidator.signer) + .mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.connect(liquidator.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const userReserveDataBefore = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address); + const aaveReserveDataBefore = await helpersContract.getReserveData(aave.address); + + const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .div(2) + .decimalPlaces(0, BigNumber.ROUND_DOWN) + .toFixed(0); + + const collateralPrice = await oracle.getAssetPrice(aave.address); + const principalPrice = await oracle.getAssetPrice(usdc.address); + + await pool + .connect(liquidator.signer) + .liquidationCall(aave.address, usdc.address, borrower.address, amountToLiquidate, false); + + const userReserveDataAfter = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + + const usdcReserveDataAfter = await helpersContract.getReserveData(usdc.address); + const aaveReserveDataAfter = await helpersContract.getReserveData(aave.address); + + const aaveConfiguration = await helpersContract.getReserveConfigurationData(aave.address); + const collateralDecimals = aaveConfiguration.decimals.toString(); + const liquidationBonus = aaveConfiguration.liquidationBonus.toString(); + + const principalDecimals = ( + await helpersContract.getReserveConfigurationData(usdc.address) + ).decimals.toString(); + + const expectedCollateralLiquidated = oneEther.multipliedBy('10'); + + const expectedPrincipal = new BigNumber(collateralPrice.toString()) + .times(expectedCollateralLiquidated) + .times(new BigNumber(10).pow(principalDecimals)) + .div( + new BigNumber(principalPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .times(10000) + .div(liquidationBonus.toString()) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + + expect(userGlobalDataAfter.healthFactor.toString()).to.be.bignumber.gt( + oneEther.toFixed(0), + 'Invalid health factor' + ); + + expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( + new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .minus(expectedPrincipal) + .toFixed(0), + 'Invalid user borrow balance after liquidation' + ); + + expect(usdcReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(usdcReserveDataBefore.availableLiquidity.toString()) + .plus(expectedPrincipal) + .toFixed(0), + 'Invalid principal available liquidity' + ); + + expect(aaveReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( + new BigNumber(aaveReserveDataBefore.availableLiquidity.toString()) + .minus(expectedCollateralLiquidated) + .toFixed(0), + 'Invalid collateral available liquidity' + ); + }); +}); diff --git a/test-suites/test-lp/mainnet/check-list.spec.ts b/test-suites/test-lp/mainnet/check-list.spec.ts new file mode 100644 index 00000000..a741dab4 --- /dev/null +++ b/test-suites/test-lp/mainnet/check-list.spec.ts @@ -0,0 +1,366 @@ +import { MAX_UINT_AMOUNT } from '../../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../../helpers/contracts-helpers'; +import { makeSuite, TestEnv } from '../helpers/make-suite'; +import { parseEther } from 'ethers/lib/utils'; +import { DRE, waitForTx } from '../../../helpers/misc-utils'; +import { BigNumber } from 'ethers'; +import { getStableDebtToken, getVariableDebtToken } from '../../../helpers/contracts-getters'; +import { deploySelfdestructTransferMock } from '../../../helpers/contracts-deployments'; +import { IUniswapV2Router02Factory } from '../../../types/IUniswapV2Router02Factory'; + +const { expect } = require('chai'); + +const UNISWAP_ROUTER = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'; + +makeSuite('Mainnet Check list', (testEnv: TestEnv) => { + const zero = BigNumber.from('0'); + const depositSize = parseEther('5'); + const daiSize = parseEther('10000'); + it('Deposit WETH', async () => { + const { users, wethGateway, aWETH, pool } = testEnv; + + const user = users[1]; + + // Deposit with native ETH + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(depositSize); + }); + + it('Withdraw WETH - Partial', async () => { + const { users, wethGateway, aWETH, pool } = testEnv; + + const user = users[1]; + const priorEthersBalance = await user.signer.getBalance(); + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.'); + + // Partially withdraw native ETH + const partialWithdraw = await convertToCurrencyDecimals(aWETH.address, '2'); + + // Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether + const approveTx = await aWETH + .connect(user.signer) + .approve(wethGateway.address, MAX_UINT_AMOUNT); + const { gasUsed: approveGas } = await waitForTx(approveTx); + + // Partial Withdraw and send native Ether to user + const { gasUsed: withdrawGas } = await waitForTx( + await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) + ); + + const afterPartialEtherBalance = await user.signer.getBalance(); + const afterPartialATokensBalance = await aWETH.balanceOf(user.address); + const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice); + + expect(afterPartialEtherBalance).to.be.equal( + priorEthersBalance.add(partialWithdraw).sub(gasCosts), + 'User ETHER balance should contain the partial withdraw' + ); + expect(afterPartialATokensBalance).to.be.equal( + aTokensBalance.sub(partialWithdraw), + 'User aWETH balance should be substracted' + ); + }); + + it('Withdraw WETH - Full', async () => { + const { users, aWETH, wethGateway, pool } = testEnv; + + const user = users[1]; + const priorEthersBalance = await user.signer.getBalance(); + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.'); + + // Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether + const approveTx = await aWETH + .connect(user.signer) + .approve(wethGateway.address, MAX_UINT_AMOUNT); + const { gasUsed: approveGas } = await waitForTx(approveTx); + + // Full withdraw + const { gasUsed: withdrawGas } = await waitForTx( + await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) + ); + + const afterFullEtherBalance = await user.signer.getBalance(); + const afterFullATokensBalance = await aWETH.balanceOf(user.address); + const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice); + + expect(afterFullEtherBalance).to.be.eq( + priorEthersBalance.add(aTokensBalance).sub(gasCosts), + 'User ETHER balance should contain the full withdraw' + ); + expect(afterFullATokensBalance).to.be.eq(0, 'User aWETH balance should be zero'); + }); + + it('Borrow stable WETH and Full Repay with ETH', async () => { + const { users, wethGateway, aWETH, dai, aDai, weth, pool, helpersContract } = testEnv; + const borrowSize = parseEther('1'); + const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); + const user = users[1]; + + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const stableDebtToken = await getStableDebtToken(stableDebtTokenAddress); + + // Deposit 10000 DAI + await dai.connect(user.signer).mint(daiSize); + await dai.connect(user.signer).approve(pool.address, daiSize); + await pool.connect(user.signer).deposit(dai.address, daiSize, user.address, '0'); + + const aTokensBalance = await aDai.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(daiSize); + + // Borrow WETH with WETH as collateral + await waitForTx( + await pool.connect(user.signer).borrow(weth.address, borrowSize, '1', '0', user.address) + ); + + const debtBalance = await stableDebtToken.balanceOf(user.address); + + expect(debtBalance).to.be.gt(zero); + + // Full Repay WETH with native ETH + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) + ); + + const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); + expect(debtBalanceAfterRepay).to.be.eq(zero); + }); + + it('Borrow variable WETH and Full Repay with ETH', async () => { + const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; + const borrowSize = parseEther('1'); + const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); + const user = users[1]; + + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + // Deposit with native ETH + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(depositSize); + + // Borrow WETH with WETH as collateral + await waitForTx( + await pool.connect(user.signer).borrow(weth.address, borrowSize, '2', '0', user.address) + ); + + const debtBalance = await varDebtToken.balanceOf(user.address); + + expect(debtBalance).to.be.gt(zero); + + // Partial Repay WETH loan with native ETH + const partialPayment = repaySize.div(2); + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(partialPayment, '2', user.address, { value: partialPayment }) + ); + + const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); + expect(debtBalanceAfterPartialRepay).to.be.lt(debtBalance); + + // Full Repay WETH loan with native ETH + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) + ); + const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); + expect(debtBalanceAfterFullRepay).to.be.eq(zero); + }); + + it('Borrow ETH via delegateApprove ETH and repays back', async () => { + const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; + const borrowSize = parseEther('1'); + const user = users[2]; + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + const priorDebtBalance = await varDebtToken.balanceOf(user.address); + expect(priorDebtBalance).to.be.eq(zero); + + // Deposit WETH with native ETH + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(depositSize); + + // Delegates borrowing power of WETH to WETHGateway + await waitForTx( + await varDebtToken.connect(user.signer).approveDelegation(wethGateway.address, borrowSize) + ); + + // Borrows ETH with WETH as collateral + await waitForTx(await wethGateway.connect(user.signer).borrowETH(borrowSize, '2', '0')); + + const debtBalance = await varDebtToken.balanceOf(user.address); + + expect(debtBalance).to.be.gt(zero); + + // Full Repay WETH loan with native ETH + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) + ); + const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); + expect(debtBalanceAfterFullRepay).to.be.eq(zero); + }); + + it('Should revert if receiver function receives Ether if not WETH', async () => { + const { users, wethGateway } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + + // Call receiver function (empty data + value) + await expect( + user.signer.sendTransaction({ + to: wethGateway.address, + value: amount, + gasLimit: DRE.network.config.gas, + }) + ).to.be.revertedWith('Receive not allowed'); + }); + + it('Should revert if fallback functions is called with Ether', async () => { + const { users, wethGateway } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + const fakeABI = ['function wantToCallFallback()']; + const abiCoder = new DRE.ethers.utils.Interface(fakeABI); + const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []); + + // Call fallback function with value + await expect( + user.signer.sendTransaction({ + to: wethGateway.address, + data: fakeMethodEncoded, + value: amount, + gasLimit: DRE.network.config.gas, + }) + ).to.be.revertedWith('Fallback not allowed'); + }); + + it('Should revert if fallback functions is called', async () => { + const { users, wethGateway } = testEnv; + const user = users[0]; + + const fakeABI = ['function wantToCallFallback()']; + const abiCoder = new DRE.ethers.utils.Interface(fakeABI); + const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []); + + // Call fallback function without value + await expect( + user.signer.sendTransaction({ + to: wethGateway.address, + data: fakeMethodEncoded, + gasLimit: DRE.network.config.gas, + }) + ).to.be.revertedWith('Fallback not allowed'); + }); + + it('Getters should retrieve correct state', async () => { + const { aWETH, weth, pool, wethGateway } = testEnv; + + const WETHAddress = await wethGateway.getWETHAddress(); + const aWETHAddress = await wethGateway.getAWETHAddress(); + const poolAddress = await wethGateway.getLendingPoolAddress(); + + expect(WETHAddress).to.be.equal(weth.address); + expect(aWETHAddress).to.be.equal(aWETH.address); + expect(poolAddress).to.be.equal(pool.address); + }); + + it('Owner can do emergency token recovery', async () => { + const { users, weth, dai, wethGateway, deployer } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + + const uniswapRouter = IUniswapV2Router02Factory.connect(UNISWAP_ROUTER, user.signer); + await uniswapRouter.swapETHForExactTokens( + amount, // 1 DAI + [weth.address, dai.address], // Uniswap paths WETH - DAI + user.address, + (await DRE.ethers.provider.getBlock('latest')).timestamp + 300, + { + value: amount, // 1 Ether, we get refund of the unneeded Ether to buy 1 DAI + } + ); + const daiBalanceAfterMint = await dai.balanceOf(user.address); + + await dai.connect(user.signer).transfer(wethGateway.address, amount); + const daiBalanceAfterBadTransfer = await dai.balanceOf(user.address); + expect(daiBalanceAfterBadTransfer).to.be.eq( + daiBalanceAfterMint.sub(amount), + 'User should have lost the funds here.' + ); + + await wethGateway + .connect(deployer.signer) + .emergencyTokenTransfer(dai.address, user.address, amount); + const daiBalanceAfterRecovery = await dai.balanceOf(user.address); + + expect(daiBalanceAfterRecovery).to.be.eq( + daiBalanceAfterMint, + 'User should recover the funds due emergency token transfer' + ); + }); + + it('Owner can do emergency native ETH recovery', async () => { + const { users, wethGateway, deployer } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + const userBalancePriorCall = await user.signer.getBalance(); + + // Deploy contract with payable selfdestruct contract + const selfdestructContract = await deploySelfdestructTransferMock(); + + // Selfdestruct the mock, pointing to WETHGateway address + const callTx = await selfdestructContract + .connect(user.signer) + .destroyAndTransfer(wethGateway.address, { value: amount }); + const { gasUsed } = await waitForTx(callTx); + const gasFees = gasUsed.mul(callTx.gasPrice); + const userBalanceAfterCall = await user.signer.getBalance(); + + expect(userBalanceAfterCall).to.be.eq(userBalancePriorCall.sub(amount).sub(gasFees), ''); + ('User should have lost the funds'); + + // Recover the funds from the contract and sends back to the user + await wethGateway.connect(deployer.signer).emergencyEtherTransfer(user.address, amount); + + const userBalanceAfterRecovery = await user.signer.getBalance(); + const wethGatewayAfterRecovery = await DRE.ethers.provider.getBalance(wethGateway.address); + + expect(userBalanceAfterRecovery).to.be.eq( + userBalancePriorCall.sub(gasFees), + 'User should recover the funds due emergency eth transfer.' + ); + expect(wethGatewayAfterRecovery).to.be.eq('0', 'WETHGateway ether balance should be zero.'); + }); +}); diff --git a/test-suites/test-lp/pausable-functions.spec.ts b/test-suites/test-lp/pausable-functions.spec.ts new file mode 100644 index 00000000..c95aaf3c --- /dev/null +++ b/test-suites/test-lp/pausable-functions.spec.ts @@ -0,0 +1,330 @@ +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors, RateMode } from '../../helpers/types'; +import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../../helpers/constants'; +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'); + +makeSuite('Pausable Pool', (testEnv: TestEnv) => { + let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver; + + const { + LP_IS_PAUSED, + INVALID_FROM_BALANCE_AFTER_TRANSFER, + INVALID_TO_BALANCE_AFTER_TRANSFER, + } = ProtocolErrors; + + before(async () => { + _mockFlashLoanReceiver = await getMockFlashLoanReceiver(); + }); + + it('User 0 deposits 1000 DAI. Configurator pauses pool. Transfers to user 1 reverts. Configurator unpauses the network and next transfer succees', async () => { + const { users, pool, dai, aDai, configurator } = testEnv; + + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await dai.connect(users[0].signer).mint(amountDAItoDeposit); + + // user 0 deposits 1000 DAI + await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool + .connect(users[0].signer) + .deposit(dai.address, amountDAItoDeposit, users[0].address, '0'); + + const user0Balance = await aDai.balanceOf(users[0].address); + const user1Balance = await aDai.balanceOf(users[1].address); + + // Configurator pauses the pool + await configurator.connect(users[1].signer).setPoolPause(true); + + // User 0 tries the transfer to User 1 + await expect( + aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit) + ).to.revertedWith(LP_IS_PAUSED); + + const pausedFromBalance = await aDai.balanceOf(users[0].address); + const pausedToBalance = await aDai.balanceOf(users[1].address); + + expect(pausedFromBalance).to.be.equal( + user0Balance.toString(), + INVALID_TO_BALANCE_AFTER_TRANSFER + ); + expect(pausedToBalance.toString()).to.be.equal( + user1Balance.toString(), + INVALID_FROM_BALANCE_AFTER_TRANSFER + ); + + // Configurator unpauses the pool + await configurator.connect(users[1].signer).setPoolPause(false); + + // User 0 succeeds transfer to User 1 + await aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit); + + const fromBalance = await aDai.balanceOf(users[0].address); + const toBalance = await aDai.balanceOf(users[1].address); + + expect(fromBalance.toString()).to.be.equal( + user0Balance.sub(amountDAItoDeposit), + INVALID_FROM_BALANCE_AFTER_TRANSFER + ); + expect(toBalance.toString()).to.be.equal( + user1Balance.add(amountDAItoDeposit), + INVALID_TO_BALANCE_AFTER_TRANSFER + ); + }); + + it('Deposit', async () => { + const { users, pool, dai, aDai, configurator } = testEnv; + + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await dai.connect(users[0].signer).mint(amountDAItoDeposit); + + // user 0 deposits 1000 DAI + await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + // Configurator pauses the pool + await configurator.connect(users[1].signer).setPoolPause(true); + await expect( + pool.connect(users[0].signer).deposit(dai.address, amountDAItoDeposit, users[0].address, '0') + ).to.revertedWith(LP_IS_PAUSED); + + // Configurator unpauses the pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('Withdraw', async () => { + const { users, pool, dai, aDai, configurator } = testEnv; + + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await dai.connect(users[0].signer).mint(amountDAItoDeposit); + + // user 0 deposits 1000 DAI + await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool + .connect(users[0].signer) + .deposit(dai.address, amountDAItoDeposit, users[0].address, '0'); + + // Configurator pauses the pool + await configurator.connect(users[1].signer).setPoolPause(true); + + // user tries to burn + await expect( + pool.connect(users[0].signer).withdraw(dai.address, amountDAItoDeposit, users[0].address) + ).to.revertedWith(LP_IS_PAUSED); + + // Configurator unpauses the pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('Borrow', async () => { + const { pool, dai, users, configurator } = testEnv; + + const user = users[1]; + // Pause the pool + await configurator.connect(users[1].signer).setPoolPause(true); + + // Try to execute liquidation + await expect( + pool.connect(user.signer).borrow(dai.address, '1', '1', '0', user.address) + ).revertedWith(LP_IS_PAUSED); + + // Unpause the pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('Repay', async () => { + const { pool, dai, users, configurator } = testEnv; + + const user = users[1]; + // Pause the pool + await configurator.connect(users[1].signer).setPoolPause(true); + + // Try to execute liquidation + await expect(pool.connect(user.signer).repay(dai.address, '1', '1', user.address)).revertedWith( + LP_IS_PAUSED + ); + + // Unpause the pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('Flash loan', async () => { + const { dai, pool, weth, users, configurator } = testEnv; + + const caller = users[3]; + + const flashAmount = parseEther('0.8'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + // Pause pool + await configurator.connect(users[1].signer).setPoolPause(true); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [flashAmount], + [1], + caller.address, + '0x10', + '0' + ) + ).revertedWith(LP_IS_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('Liquidation call', async () => { + const { users, pool, usdc, oracle, weth, configurator, helpersContract } = testEnv; + const depositor = users[3]; + const borrower = users[4]; + + //mints USDC to depositor + await usdc + .connect(depositor.signer) + .mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 3 deposits 1000 USDC + const amountUSDCtoDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(usdc.address, amountUSDCtoDeposit, depositor.address, '0'); + + //user 4 deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(amountETHtoDeposit); + + //approve protocol to access borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 4 borrows + const userGlobalData = await pool.getUserAccountData(borrower.address); + + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const amountUSDCToBorrow = await convertToCurrencyDecimals( + usdc.address, + new BigNumber(userGlobalData.availableBorrowsETH.toString()) + .div(usdcPrice.toString()) + .multipliedBy(0.9502) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); + + // Drops HF below 1 + await oracle.setAssetPrice( + usdc.address, + new BigNumber(usdcPrice.toString()).multipliedBy(1.2).toFixed(0) + ); + + //mints dai to the liquidator + await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000')); + await usdc.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const userReserveDataBefore = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .multipliedBy(0.5) + .toFixed(0); + + // Pause pool + await configurator.connect(users[1].signer).setPoolPause(true); + + // Do liquidation + await expect( + pool.liquidationCall(weth.address, usdc.address, borrower.address, amountToLiquidate, true) + ).revertedWith(LP_IS_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('SwapBorrowRateMode', async () => { + const { pool, weth, dai, usdc, users, configurator } = testEnv; + const user = users[1]; + const amountWETHToDeposit = parseEther('10'); + const amountDAIToDeposit = parseEther('120'); + const amountToBorrow = parseUnits('65', 6); + + await weth.connect(user.signer).mint(amountWETHToDeposit); + await weth.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool.connect(user.signer).deposit(weth.address, amountWETHToDeposit, user.address, '0'); + + await dai.connect(user.signer).mint(amountDAIToDeposit); + await dai.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool.connect(user.signer).deposit(dai.address, amountDAIToDeposit, user.address, '0'); + + await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0, user.address); + + // Pause pool + await configurator.connect(users[1].signer).setPoolPause(true); + + // Try to repay + await expect( + pool.connect(user.signer).swapBorrowRateMode(usdc.address, RateMode.Stable) + ).revertedWith(LP_IS_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('RebalanceStableBorrowRate', async () => { + const { pool, dai, users, configurator } = testEnv; + const user = users[1]; + // Pause pool + await configurator.connect(users[1].signer).setPoolPause(true); + + await expect( + pool.connect(user.signer).rebalanceStableBorrowRate(dai.address, user.address) + ).revertedWith(LP_IS_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); + + it('setUserUseReserveAsCollateral', async () => { + const { pool, weth, users, configurator } = testEnv; + const user = users[1]; + + const amountWETHToDeposit = parseEther('1'); + await weth.connect(user.signer).mint(amountWETHToDeposit); + await weth.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool.connect(user.signer).deposit(weth.address, amountWETHToDeposit, user.address, '0'); + + // Pause pool + await configurator.connect(users[1].signer).setPoolPause(true); + + await expect( + pool.connect(user.signer).setUserUseReserveAsCollateral(weth.address, false) + ).revertedWith(LP_IS_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).setPoolPause(false); + }); +}); diff --git a/test-suites/test-lp/pool-modifiers.spec.ts b/test-suites/test-lp/pool-modifiers.spec.ts new file mode 100644 index 00000000..fb915b15 --- /dev/null +++ b/test-suites/test-lp/pool-modifiers.spec.ts @@ -0,0 +1,241 @@ +// import {iATokenBase, iAssetsWithoutETH, ITestEnvWithoutInstances, RateMode} from '../utils/types'; +// import { +// LendingPoolConfiguratorInstance, +// LendingPoolInstance, +// ATokenInstance, +// LendingPoolCoreInstance, +// MintableERC20Instance, +// } from '../utils/typechain-types/truffle-contracts'; +// import {testEnvProviderWithoutInstances} from '../utils/truffle/dlp-tests-env'; +// import {oneEther, ETHEREUM_ADDRESS} from '../utils/constants'; +// import {convertToCurrencyDecimals} from '../utils/misc-utils'; + +// const expectRevert = require('@openzeppelin/test-helpers').expectRevert; + +// contract('LendingPool: Modifiers', async ([deployer, ...users]) => { +// let _testEnvProvider: ITestEnvWithoutInstances; +// let _lendingPoolConfiguratorInstance: LendingPoolConfiguratorInstance; +// let _lendingPoolInstance: LendingPoolInstance; +// let _lendingPoolCoreInstance: LendingPoolCoreInstance; +// let _aTokenInstances: iATokenBase; +// let _tokenInstances: iAssetsWithoutETH; + +// before('Initializing LendingPool test variables', async () => { +// console.time('setup-test'); +// _testEnvProvider = await testEnvProviderWithoutInstances(artifacts, [deployer, ...users]); + +// const { +// getAllAssetsInstances, +// getLendingPoolInstance, +// getLendingPoolCoreInstance, +// getLendingPoolConfiguratorInstance, +// getATokenInstances, +// } = _testEnvProvider; +// const instances = await Promise.all([ +// getLendingPoolInstance(), +// getLendingPoolCoreInstance(), +// getLendingPoolConfiguratorInstance(), +// getATokenInstances(), +// getAllAssetsInstances(), +// ]); + +// _lendingPoolInstance = instances[0]; +// _lendingPoolCoreInstance = instances[1]; +// _lendingPoolConfiguratorInstance = instances[2]; + +// _aTokenInstances = instances[3]; +// _tokenInstances = instances[4]; +// console.timeEnd('setup-test'); +// }); + +// it('Tries to deposit in an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.deposit(deployer, '1', '0'), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to invoke redeemUnderlying on an reserve, from a non-aToken address', async () => { +// await expectRevert( +// _lendingPoolInstance.redeemUnderlying(ETHEREUM_ADDRESS, deployer, '1', '0'), +// 'The caller of this function can only be the aToken contract of this reserve' +// ); +// }); + +// it('Tries to borrow from an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.borrow(deployer, '1', '0', RateMode.Stable), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to repay in an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.repay(deployer, '1', deployer), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to swapBorrowRateMode on an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.swapBorrowRateMode(deployer), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to rebalanceStableBorrowRate on an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.rebalanceStableBorrowRate(deployer, deployer), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to setUserUseReserveAsCollateral on an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.setUserUseReserveAsCollateral(deployer, true), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to invoke liquidationCall on an inactive reserve', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.liquidationCall(ETHEREUM_ADDRESS, deployer, deployer, '1', false), +// 'Action requires an active reserve' +// ); +// }); + +// it('Tries to invoke liquidationCall on an inactive collateral', async () => { +// //using the deployer address as a fake reserve address +// await expectRevert( +// _lendingPoolInstance.liquidationCall(deployer, ETHEREUM_ADDRESS, deployer, '1', false), +// 'Action requires an active reserve' +// ); +// }); + +// it('Freezes the ETH reserve', async () => { +// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS); +// }); + +// it('tries to deposit in a freezed reserve', async () => { +// await expectRevert( +// _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, '1', '0'), +// 'Action requires an unfreezed reserve' +// ); +// }); + +// it('tries to borrow from a freezed reserve', async () => { +// await expectRevert( +// _lendingPoolInstance.borrow(ETHEREUM_ADDRESS, '1', '0', '0'), +// 'Action requires an unfreezed reserve' +// ); +// }); + +// it('tries to swap interest rate mode in a freezed reserve', async () => { +// await expectRevert( +// _lendingPoolInstance.swapBorrowRateMode(ETHEREUM_ADDRESS), +// 'Action requires an unfreezed reserve' +// ); +// }); + +// it('tries to disable as collateral a freezed reserve', async () => { +// await expectRevert( +// _lendingPoolInstance.setUserUseReserveAsCollateral(ETHEREUM_ADDRESS, false), +// 'Action requires an unfreezed reserve' +// ); +// }); + +// it('unfreezes the reserve, user deposits 1 ETH, freezes the reserve, check that the user can redeem', async () => { +// const {aWETH} = _aTokenInstances; + +// //unfreezes the reserve +// await _lendingPoolConfiguratorInstance.unfreezeReserve(ETHEREUM_ADDRESS); + +// //deposit 1 ETH +// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, oneEther, '0', { +// value: oneEther.toString(), +// }); + +// //freezes the reserve +// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS); + +// const balance = await aWETH.balanceOf(deployer); + +// await aWETH.redeem(balance); +// }); + +// it('unfreezes the reserve, user 0 deposits 100 DAI, user 1 deposits 1 ETH and borrows 50 DAI, freezes the reserve, checks that the user 1 can repay', async () => { +// const {aWETH, aDAI} = _aTokenInstances; +// const {DAI} = _tokenInstances; + +// //unfreezes the reserve +// await _lendingPoolConfiguratorInstance.unfreezeReserve(ETHEREUM_ADDRESS); + +// const amountDAI = await convertToCurrencyDecimals(DAI.address, '100'); + +// //user 0 deposits 100 DAI +// await DAI.mint(amountDAI, {from: users[0]}); + +// await DAI.approve(_lendingPoolCoreInstance.address, amountDAI, {from: users[0]}); + +// await _lendingPoolInstance.deposit(DAI.address, amountDAI, '0', {from: users[0]}); + +// //user 1 deposits 1 ETH +// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, oneEther, '0', { +// from: users[1], +// value: oneEther.toString(), +// }); + +// const amountDAIToBorrow = await convertToCurrencyDecimals(DAI.address, '10'); + +// //user 1 borrows 10 DAI +// await _lendingPoolInstance.borrow(DAI.address, amountDAIToBorrow, RateMode.Stable, '0', { +// from: users[1], +// }); + +// //freezes the reserve +// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS); + +// //user 1 repays 1 DAI +// await DAI.approve(_lendingPoolCoreInstance.address, amountDAIToBorrow, {from: users[1]}); + +// await _lendingPoolInstance.repay(DAI.address, oneEther, users[1], {from: users[1]}); +// }); + +// it('Check that liquidationCall can be executed on a freezed reserve', async () => { +// const {aWETH, aDAI} = _aTokenInstances; +// const {DAI} = _tokenInstances; + +// //user 2 tries to liquidate + +// await expectRevert( +// _lendingPoolInstance.liquidationCall( +// ETHEREUM_ADDRESS, +// DAI.address, +// users[1], +// oneEther, +// true, +// {from: users[2]} +// ), +// 'Health factor is not below the threshold' +// ); +// }); + +// it('Check that rebalanceStableBorrowRate can be executed on a freezed reserve', async () => { +// const {aWETH, aDAI} = _aTokenInstances; +// const {DAI} = _tokenInstances; + +// //user 2 tries to liquidate + +// await expectRevert( +// _lendingPoolInstance.rebalanceStableBorrowRate(DAI.address, users[1]), +// 'Interest rate rebalance conditions were not met' +// ); +// }); +// }); diff --git a/test-suites/test-lp/rate-strategy.spec.ts b/test-suites/test-lp/rate-strategy.spec.ts new file mode 100644 index 00000000..b56c754e --- /dev/null +++ b/test-suites/test-lp/rate-strategy.spec.ts @@ -0,0 +1,165 @@ +// import { +// IReserveParams, +// iAavePoolAssets, +// iAssetsWithoutETH, +// ITestEnvWithoutInstances, +// } from "../utils/types" +// import { + +// LendingPoolAddressesProviderInstance, + +// DefaultReserveInterestRateStrategyInstance, +// MintableERC20Instance, +// } from "../utils/typechain-types/truffle-contracts" +// import { testEnvProviderWithoutInstances} from "../utils/truffle/dlp-tests-env" +// import {RAY} from "../utils/constants" +// import BigNumber from "bignumber.js" + +// const {expect} = require("chai") + +// contract("Interest rate strategy", async ([deployer, ...users]) => { +// let _testEnvProvider: ITestEnvWithoutInstances +// let _strategyInstance: DefaultReserveInterestRateStrategyInstance +// let _tokenInstances: iAssetsWithoutETH +// let _addressesProviderInstance: LendingPoolAddressesProviderInstance +// let _reservesParams: iAavePoolAssets + +// before("Initializing test variables", async () => { +// console.time('setup-test'); +// _testEnvProvider = await testEnvProviderWithoutInstances( +// artifacts, +// [deployer, ...users], +// ) + +// const { +// getAllAssetsInstances, +// getLendingPoolAddressesProviderInstance, +// getAavePoolReservesParams, +// } = _testEnvProvider + +// const instances = await Promise.all([ +// getAllAssetsInstances(), +// getLendingPoolAddressesProviderInstance() +// ]) + +// _tokenInstances = instances[0] +// _addressesProviderInstance = instances[1] +// _reservesParams = await getAavePoolReservesParams() +// console.timeEnd('setup-test'); +// }) + +// it("Deploys a new instance of a DefaultReserveInterestRateStrategy contract", async () => { +// const {DAI: daiInstance} = _tokenInstances + +// const {DAI: daiConfiguration} = _reservesParams + +// const contract: any = await artifacts.require("DefaultReserveInterestRateStrategy") +// const mathLibrary = await artifacts.require("WadRayMath") +// const mathLibraryInstance = await mathLibrary.new() + +// await contract.link("WadRayMath", mathLibraryInstance.address) + +// _strategyInstance = await contract.new( +// daiInstance.address, +// _addressesProviderInstance.address, +// daiConfiguration.baseVariableBorrowRate, +// daiConfiguration.variableRateSlope1, +// daiConfiguration.variableRateSlope2, +// daiConfiguration.stableRateSlope1, +// daiConfiguration.stableRateSlope2, +// ) +// }) + +// it("Checks rates at 0% utilization rate", async () => { +// const {DAI: daiInstance} = _tokenInstances +// const {DAI: daiConfiguration} = _reservesParams +// const data: any = await _strategyInstance.calculateInterestRates( +// daiInstance.address, +// "1000000000000000000", +// "0", +// "0", +// "0", +// ) + +// expect(data.currentLiquidityRate.toString()).to.be.equal("0", "Invalid liquidity rate") +// expect(data.currentStableBorrowRate.toString()).to.be.equal( +// new BigNumber(0.039).times(RAY).toFixed(0), +// "Invalid stable rate", +// ) +// expect(data.currentVariableBorrowRate.toString()).to.be.equal( +// daiConfiguration.baseVariableBorrowRate, +// "Invalid variable rate", +// ) +// }) + +// it("Checks rates at 80% utilization rate", async () => { +// const {DAI: daiInstance} = _tokenInstances +// const {DAI: daiConfiguration} = _reservesParams +// const data: any = await _strategyInstance.calculateInterestRates( +// daiInstance.address, +// "200000000000000000", +// "0", +// "800000000000000000", +// "0", +// ) + +// const expectedVariableRate = new BigNumber(daiConfiguration.baseVariableBorrowRate) +// .plus(daiConfiguration.variableRateSlope1) + +// expect(data.currentLiquidityRate.toString()).to.be.equal( +// expectedVariableRate.times(0.8).toFixed(0), +// "Invalid liquidity rate", +// ) + +// expect(data.currentVariableBorrowRate.toString()).to.be.equal( +// new BigNumber(daiConfiguration.baseVariableBorrowRate) +// .plus(daiConfiguration.variableRateSlope1) +// .toFixed(0), +// "Invalid variable rate", +// ) + +// expect(data.currentStableBorrowRate.toString()).to.be.equal( +// new BigNumber(0.039) +// .times(RAY) +// .plus(daiConfiguration.stableRateSlope1) +// .toFixed(0), +// "Invalid stable rate", +// ) +// }) + +// it("Checks rates at 100% utilization rate", async () => { +// const {DAI: daiInstance} = _tokenInstances +// const {DAI: daiConfiguration} = _reservesParams +// const data: any = await _strategyInstance.calculateInterestRates( +// daiInstance.address, +// "0", +// "0", +// "1000000000000000000", +// "0", +// ) + +// const expectedVariableRate = new BigNumber(daiConfiguration.baseVariableBorrowRate) +// .plus(daiConfiguration.variableRateSlope1) +// .plus(daiConfiguration.variableRateSlope2) +// .toFixed(0) + +// expect(data.currentLiquidityRate.toString()).to.be.equal( +// expectedVariableRate, +// "Invalid liquidity rate", +// ) + +// expect(data.currentVariableBorrowRate.toString()).to.be.equal( +// expectedVariableRate, +// "Invalid variable rate", +// ) + +// expect(data.currentStableBorrowRate.toString()).to.be.equal( +// new BigNumber(0.039) +// .times(RAY) +// .plus(daiConfiguration.stableRateSlope1) +// .plus(daiConfiguration.stableRateSlope2) +// .toFixed(0), +// "Invalid stable rate", +// ) +// }) +// }) diff --git a/test-suites/test-lp/scenario.spec.ts b/test-suites/test-lp/scenario.spec.ts new file mode 100644 index 00000000..03a485d6 --- /dev/null +++ b/test-suites/test-lp/scenario.spec.ts @@ -0,0 +1,44 @@ +import { configuration as actionsConfiguration } from './helpers/actions'; +import { configuration as calculationsConfiguration } from './helpers/utils/calculations'; + +import fs from 'fs'; +import BigNumber from 'bignumber.js'; +import { makeSuite } from './helpers/make-suite'; +import { getReservesConfigByPool } from '../../helpers/configuration'; +import { AavePools, iUniswapPoolAssets, IReserveParams } from '../../helpers/types'; +import { executeStory } from './helpers/scenario-engine'; + +const scenarioFolder = './test/helpers/scenarios/'; + +const selectedScenarios: string[] = []; + +fs.readdirSync(scenarioFolder).forEach((file) => { + if (selectedScenarios.length > 0 && !selectedScenarios.includes(file)) return; + + const scenario = require(`./helpers/scenarios/${file}`); + + makeSuite(scenario.title, async (testEnv) => { + before('Initializing configuration', async () => { + // Sets BigNumber for this suite, instead of globally + BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); + + actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage + + calculationsConfiguration.reservesParams = >( + getReservesConfigByPool(AavePools.uniswap) + ); + }); + after('Reset', () => { + // Reset BigNumber + BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); + }); + + for (const story of scenario.stories) { + it(story.description, async function () { + // Retry the test scenarios up to 4 times if an error happens, due erratic HEVM network errors + this.retries(4); + await executeStory(story, testEnv); + }); + } + }); +}); diff --git a/test-suites/test-lp/stable-rate-economy.spec.ts b/test-suites/test-lp/stable-rate-economy.spec.ts new file mode 100644 index 00000000..1c2c156a --- /dev/null +++ b/test-suites/test-lp/stable-rate-economy.spec.ts @@ -0,0 +1,199 @@ +// import { +// LendingPoolInstance, +// LendingPoolCoreInstance, +// MintableERC20Instance, +// ATokenInstance, +// } from "../utils/typechain-types/truffle-contracts" +// import { +// iATokenBase, +// iAssetsWithoutETH, +// ITestEnvWithoutInstances, +// RateMode, +// } from "../utils/types" +// import { +// APPROVAL_AMOUNT_LENDING_POOL_CORE, +// ETHEREUM_ADDRESS, +// } from "../utils/constants" +// import { testEnvProviderWithoutInstances} from "../utils/truffle/dlp-tests-env" +// import {convertToCurrencyDecimals} from "../utils/misc-utils" + +// const expectRevert = require("@openzeppelin/test-helpers").expectRevert + +// contract("LendingPool - stable rate economy tests", async ([deployer, ...users]) => { +// let _testEnvProvider: ITestEnvWithoutInstances +// let _lendingPoolInstance: LendingPoolInstance +// let _lendingPoolCoreInstance: LendingPoolCoreInstance +// let _aTokenInstances: iATokenBase +// let _tokenInstances: iAssetsWithoutETH + +// let _daiAddress: string + +// let _depositorAddress: string +// let _borrowerAddress: string + +// let _web3: Web3 + +// before("Initializing LendingPool test variables", async () => { +// console.time('setup-test'); +// _testEnvProvider = await testEnvProviderWithoutInstances( +// artifacts, +// [deployer, ...users] +// ) + +// const { +// getWeb3, +// getAllAssetsInstances, +// getFirstBorrowerAddressOnTests, +// getFirstDepositorAddressOnTests, +// getLendingPoolInstance, +// getLendingPoolCoreInstance, +// getATokenInstances +// } = _testEnvProvider + +// const instances = await Promise.all([ +// getLendingPoolInstance(), +// getLendingPoolCoreInstance(), +// getATokenInstances(), +// getAllAssetsInstances() +// ]) +// _lendingPoolInstance = instances[0] +// _lendingPoolCoreInstance = instances[1] +// _aTokenInstances = instances[2] +// _tokenInstances = instances[3] +// _daiAddress = _tokenInstances.DAI.address +// _depositorAddress = await getFirstDepositorAddressOnTests() +// _borrowerAddress = await getFirstBorrowerAddressOnTests() + +// _web3 = await getWeb3() +// console.timeEnd('setup-test'); +// }) + +// it("BORROW - Test user cannot borrow using the same currency as collateral", async () => { +// const {aDAI: aDaiInstance} = _aTokenInstances +// const {DAI: daiInstance} = _tokenInstances + +// //mints DAI to depositor +// await daiInstance.mint(await convertToCurrencyDecimals(daiInstance.address, "1000"), { +// from: _depositorAddress, +// }) + +// //mints DAI to borrower +// await daiInstance.mint(await convertToCurrencyDecimals(daiInstance.address, "1000"), { +// from: _borrowerAddress, +// }) + +// //approve protocol to access depositor wallet +// await daiInstance.approve(_lendingPoolCoreInstance.address, APPROVAL_AMOUNT_LENDING_POOL_CORE, { +// from: _depositorAddress, +// }) + +// //approve protocol to access borrower wallet +// await daiInstance.approve(_lendingPoolCoreInstance.address, APPROVAL_AMOUNT_LENDING_POOL_CORE, { +// from: _borrowerAddress, +// }) + +// const amountDAItoDeposit = await convertToCurrencyDecimals(_daiAddress, "1000") + +// //user 1 deposits 1000 DAI +// const txResult = await _lendingPoolInstance.deposit(_daiAddress, amountDAItoDeposit, "0", { +// from: _depositorAddress, +// }) + +// //user 2 deposits 1000 DAI, tries to borrow. Needs to be reverted as you can't borrow at a stable rate with the same collateral as the currency. +// const amountDAIToDepositBorrower = await convertToCurrencyDecimals(_daiAddress, "1000") +// await _lendingPoolInstance.deposit(_daiAddress, amountDAIToDepositBorrower, "0", { +// from: _borrowerAddress, +// }) + +// const data: any = await _lendingPoolInstance.getReserveData(_daiAddress) + +// //user 2 tries to borrow +// const amountDAIToBorrow = await convertToCurrencyDecimals(_daiAddress, "250") + +// //user 2 tries to borrow +// await expectRevert( +// _lendingPoolInstance.borrow(_daiAddress, amountDAIToBorrow, RateMode.Stable, "0", { +// from: _borrowerAddress, +// }), +// "User cannot borrow the selected amount with a stable rate", +// ) +// }) + +// it("BORROW - Test user cannot borrow more than 25% of the liquidity available", async () => { +// const {aDAI: aDaiInstance} = _aTokenInstances +// const {DAI: daiInstance} = _tokenInstances + +// //redeem the DAI previously deposited +// const amountADAIToRedeem = await convertToCurrencyDecimals(aDaiInstance.address, "1000") +// await aDaiInstance.redeem(amountADAIToRedeem, { +// from: _borrowerAddress, +// }) + +// //user 2 deposits 5 ETH tries to borrow. needs to be reverted as you can't borrow more than 25% of the available reserve (250 DAI) +// const amountETHToDeposit = await convertToCurrencyDecimals(ETHEREUM_ADDRESS, "5") +// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, amountETHToDeposit, "0", { +// from: _borrowerAddress, +// value: amountETHToDeposit, +// }) + +// const data: any = await _lendingPoolInstance.getReserveData(_daiAddress) + +// const amountDAIToBorrow = await convertToCurrencyDecimals(_daiAddress, "500") + +// //user 2 tries to borrow +// await expectRevert( +// _lendingPoolInstance.borrow(_daiAddress, amountDAIToBorrow, RateMode.Stable, "0", { +// from: _borrowerAddress, +// }), +// "User is trying to borrow too much liquidity at a stable rate", +// ) +// }) + +// it("BORROW - Test user can still borrow a currency that he previously deposited as a collateral but he transferred/redeemed", async () => { +// const {aDAI: aDaiInstance} = _aTokenInstances +// const {DAI: daiInstance} = _tokenInstances + +// const user = users[2] + +// //user deposits 1000 DAI +// await daiInstance.mint(await convertToCurrencyDecimals(daiInstance.address, "1000"), { +// from: user, +// }) +// await daiInstance.approve(_lendingPoolCoreInstance.address, APPROVAL_AMOUNT_LENDING_POOL_CORE, { +// from: user, +// }) + +// const amountDAIToDeposit = await convertToCurrencyDecimals(daiInstance.address, "1000") +// await _lendingPoolInstance.deposit(daiInstance.address, amountDAIToDeposit, "0", { +// from: user, +// }) + +// //user deposits 5 ETH as collateral +// const amountETHToDeposit = await convertToCurrencyDecimals(ETHEREUM_ADDRESS, "5") +// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, amountETHToDeposit, "0", { +// from: user, +// value: amountETHToDeposit, +// }) + +// //user transfers to another address all the overlying aDAI + +// const aDAIBalance = await aDaiInstance.balanceOf(user) + +// await aDaiInstance.transfer(users[3], aDAIBalance, { +// from: user, +// }) + +// //check the underlying balance is 0 +// const userData: any = await _lendingPoolInstance.getUserReserveData(daiInstance.address, user) + +// expect(userData.currentATokenBalance.toString()).to.be.equal("0") + +// //user tries to borrow the DAI at a stable rate using the ETH as collateral +// const amountDAIToBorrow = await convertToCurrencyDecimals(_daiAddress, "100") + +// //user tries to borrow. No revert expected +// await _lendingPoolInstance.borrow(_daiAddress, amountDAIToBorrow, RateMode.Stable, "0", { +// from: user, +// }) +// }) +// }) diff --git a/test-suites/test-lp/stable-token.spec.ts b/test-suites/test-lp/stable-token.spec.ts new file mode 100644 index 00000000..9974c5e2 --- /dev/null +++ b/test-suites/test-lp/stable-token.spec.ts @@ -0,0 +1,37 @@ +import { expect } from 'chai'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors } from '../../helpers/types'; +import { getStableDebtToken } from '../../helpers/contracts-getters'; + +makeSuite('Stable debt token tests', (testEnv: TestEnv) => { + const { CT_CALLER_MUST_BE_LENDING_POOL } = ProtocolErrors; + + it('Tries to invoke mint not being the LendingPool', async () => { + const { deployer, pool, dai, helpersContract } = testEnv; + + const daiStableDebtTokenAddress = (await helpersContract.getReserveTokensAddresses(dai.address)) + .stableDebtTokenAddress; + + const stableDebtContract = await getStableDebtToken(daiStableDebtTokenAddress); + + await expect( + stableDebtContract.mint(deployer.address, deployer.address, '1', '1') + ).to.be.revertedWith(CT_CALLER_MUST_BE_LENDING_POOL); + }); + + it('Tries to invoke burn not being the LendingPool', async () => { + const { deployer, dai, helpersContract } = testEnv; + + const daiStableDebtTokenAddress = (await helpersContract.getReserveTokensAddresses(dai.address)) + .stableDebtTokenAddress; + + const stableDebtContract = await getStableDebtToken(daiStableDebtTokenAddress); + + const name = await stableDebtContract.name(); + + expect(name).to.be.equal('Aave stable debt bearing UniDAI'); + await expect(stableDebtContract.burn(deployer.address, '1')).to.be.revertedWith( + CT_CALLER_MUST_BE_LENDING_POOL + ); + }); +}); diff --git a/test-suites/test-lp/subgraph-scenarios.spec.ts b/test-suites/test-lp/subgraph-scenarios.spec.ts new file mode 100644 index 00000000..3aaee4ba --- /dev/null +++ b/test-suites/test-lp/subgraph-scenarios.spec.ts @@ -0,0 +1,32 @@ +import { configuration as actionsConfiguration } from './helpers/actions'; +import { configuration as calculationsConfiguration } from './helpers/utils/calculations'; + +import BigNumber from 'bignumber.js'; +import { makeSuite } from './helpers/make-suite'; +import { getReservesConfigByPool } from '../../helpers/configuration'; +import { AavePools, iUniswapPoolAssets, IReserveParams } from '../../helpers/types'; +import { executeStory } from './helpers/scenario-engine'; + +makeSuite('Subgraph scenario tests', async (testEnv) => { + let story: any; + let scenario; + before('Initializing configuration', async () => { + const scenario = require(`./helpers/scenarios/borrow-repay-stable`); + story = scenario.stories[0]; + // Sets BigNumber for this suite, instead of globally + BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); + + actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage + + calculationsConfiguration.reservesParams = >( + getReservesConfigByPool(AavePools.uniswap) + ); + }); + after('Reset', () => { + // Reset BigNumber + BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); + }); + it('deposit-borrow', async () => { + await executeStory(story, testEnv); + }); +}); diff --git a/test-suites/test-lp/uniswapAdapters.base.spec.ts b/test-suites/test-lp/uniswapAdapters.base.spec.ts new file mode 100644 index 00000000..85134cb0 --- /dev/null +++ b/test-suites/test-lp/uniswapAdapters.base.spec.ts @@ -0,0 +1,227 @@ +// import { makeSuite, TestEnv } from './helpers/make-suite'; +// import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +// import { getMockUniswapRouter } from '../../helpers/contracts-getters'; +// import { MockUniswapV2Router02 } from '../../types/MockUniswapV2Router02'; +// import BigNumber from 'bignumber.js'; +// import { evmRevert, evmSnapshot } from '../../helpers/misc-utils'; +// import { ethers } from 'ethers'; +// import { USD_ADDRESS } from '../../helpers/constants'; +// const { parseEther } = ethers.utils; + +// const { expect } = require('chai'); + +// makeSuite('Uniswap adapters', (testEnv: TestEnv) => { +// let mockUniswapRouter: MockUniswapV2Router02; +// let evmSnapshotId: string; + +// before(async () => { +// mockUniswapRouter = await getMockUniswapRouter(); +// }); + +// beforeEach(async () => { +// evmSnapshotId = await evmSnapshot(); +// }); + +// afterEach(async () => { +// await evmRevert(evmSnapshotId); +// }); + +// describe('BaseUniswapAdapter', () => { +// describe('getAmountsOut', () => { +// it('should return the estimated amountOut and prices for the asset swap', async () => { +// const { weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv; + +// const amountIn = parseEther('1'); +// const flashloanPremium = amountIn.mul(9).div(10000); +// const amountToSwap = amountIn.sub(flashloanPremium); + +// const wethPrice = await oracle.getAssetPrice(weth.address); +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const usdPrice = await oracle.getAssetPrice(USD_ADDRESS); + +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountToSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// const outPerInPrice = amountToSwap +// .mul(parseEther('1')) +// .mul(parseEther('1')) +// .div(expectedDaiAmount.mul(parseEther('1'))); +// const ethUsdValue = amountIn +// .mul(wethPrice) +// .div(parseEther('1')) +// .mul(usdPrice) +// .div(parseEther('1')); +// const daiUsdValue = expectedDaiAmount +// .mul(daiPrice) +// .div(parseEther('1')) +// .mul(usdPrice) +// .div(parseEther('1')); + +// await mockUniswapRouter.setAmountOut( +// amountToSwap, +// weth.address, +// dai.address, +// expectedDaiAmount +// ); + +// const result = await uniswapLiquiditySwapAdapter.getAmountsOut( +// amountIn, +// weth.address, +// dai.address +// ); + +// expect(result['0']).to.be.eq(expectedDaiAmount); +// expect(result['1']).to.be.eq(outPerInPrice); +// expect(result['2']).to.be.eq(ethUsdValue); +// expect(result['3']).to.be.eq(daiUsdValue); +// }); +// it('should work correctly with different decimals', async () => { +// const { aave, usdc, uniswapLiquiditySwapAdapter, oracle } = testEnv; + +// const amountIn = parseEther('10'); +// const flashloanPremium = amountIn.mul(9).div(10000); +// const amountToSwap = amountIn.sub(flashloanPremium); + +// const aavePrice = await oracle.getAssetPrice(aave.address); +// const usdcPrice = await oracle.getAssetPrice(usdc.address); +// const usdPrice = await oracle.getAssetPrice(USD_ADDRESS); + +// const expectedUSDCAmount = await convertToCurrencyDecimals( +// usdc.address, +// new BigNumber(amountToSwap.toString()).div(usdcPrice.toString()).toFixed(0) +// ); + +// const outPerInPrice = amountToSwap +// .mul(parseEther('1')) +// .mul('1000000') // usdc 6 decimals +// .div(expectedUSDCAmount.mul(parseEther('1'))); + +// const aaveUsdValue = amountIn +// .mul(aavePrice) +// .div(parseEther('1')) +// .mul(usdPrice) +// .div(parseEther('1')); + +// const usdcUsdValue = expectedUSDCAmount +// .mul(usdcPrice) +// .div('1000000') // usdc 6 decimals +// .mul(usdPrice) +// .div(parseEther('1')); + +// await mockUniswapRouter.setAmountOut( +// amountToSwap, +// aave.address, +// usdc.address, +// expectedUSDCAmount +// ); + +// const result = await uniswapLiquiditySwapAdapter.getAmountsOut( +// amountIn, +// aave.address, +// usdc.address +// ); + +// expect(result['0']).to.be.eq(expectedUSDCAmount); +// expect(result['1']).to.be.eq(outPerInPrice); +// expect(result['2']).to.be.eq(aaveUsdValue); +// expect(result['3']).to.be.eq(usdcUsdValue); +// }); +// }); + +// describe('getAmountsIn', () => { +// it('should return the estimated required amountIn for the asset swap', async () => { +// const { weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv; + +// const amountIn = parseEther('1'); +// const flashloanPremium = amountIn.mul(9).div(10000); +// const amountToSwap = amountIn.add(flashloanPremium); + +// const wethPrice = await oracle.getAssetPrice(weth.address); +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const usdPrice = await oracle.getAssetPrice(USD_ADDRESS); + +// const amountOut = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountIn.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// const inPerOutPrice = amountOut +// .mul(parseEther('1')) +// .mul(parseEther('1')) +// .div(amountToSwap.mul(parseEther('1'))); + +// const ethUsdValue = amountToSwap +// .mul(wethPrice) +// .div(parseEther('1')) +// .mul(usdPrice) +// .div(parseEther('1')); +// const daiUsdValue = amountOut +// .mul(daiPrice) +// .div(parseEther('1')) +// .mul(usdPrice) +// .div(parseEther('1')); + +// await mockUniswapRouter.setAmountIn(amountOut, weth.address, dai.address, amountIn); + +// const result = await uniswapLiquiditySwapAdapter.getAmountsIn( +// amountOut, +// weth.address, +// dai.address +// ); + +// expect(result['0']).to.be.eq(amountToSwap); +// expect(result['1']).to.be.eq(inPerOutPrice); +// expect(result['2']).to.be.eq(ethUsdValue); +// expect(result['3']).to.be.eq(daiUsdValue); +// }); +// it('should work correctly with different decimals', async () => { +// const { aave, usdc, uniswapLiquiditySwapAdapter, oracle } = testEnv; + +// const amountIn = parseEther('10'); +// const flashloanPremium = amountIn.mul(9).div(10000); +// const amountToSwap = amountIn.add(flashloanPremium); + +// const aavePrice = await oracle.getAssetPrice(aave.address); +// const usdcPrice = await oracle.getAssetPrice(usdc.address); +// const usdPrice = await oracle.getAssetPrice(USD_ADDRESS); + +// const amountOut = await convertToCurrencyDecimals( +// usdc.address, +// new BigNumber(amountToSwap.toString()).div(usdcPrice.toString()).toFixed(0) +// ); + +// const inPerOutPrice = amountOut +// .mul(parseEther('1')) +// .mul(parseEther('1')) +// .div(amountToSwap.mul('1000000')); // usdc 6 decimals + +// const aaveUsdValue = amountToSwap +// .mul(aavePrice) +// .div(parseEther('1')) +// .mul(usdPrice) +// .div(parseEther('1')); + +// const usdcUsdValue = amountOut +// .mul(usdcPrice) +// .div('1000000') // usdc 6 decimals +// .mul(usdPrice) +// .div(parseEther('1')); + +// await mockUniswapRouter.setAmountIn(amountOut, aave.address, usdc.address, amountIn); + +// const result = await uniswapLiquiditySwapAdapter.getAmountsIn( +// amountOut, +// aave.address, +// usdc.address +// ); + +// expect(result['0']).to.be.eq(amountToSwap); +// expect(result['1']).to.be.eq(inPerOutPrice); +// expect(result['2']).to.be.eq(aaveUsdValue); +// expect(result['3']).to.be.eq(usdcUsdValue); +// }); +// }); +// }); +// }); diff --git a/test-suites/test-lp/uniswapAdapters.flashLiquidation.spec.ts b/test-suites/test-lp/uniswapAdapters.flashLiquidation.spec.ts new file mode 100644 index 00000000..71b365bb --- /dev/null +++ b/test-suites/test-lp/uniswapAdapters.flashLiquidation.spec.ts @@ -0,0 +1,850 @@ +// import { makeSuite, TestEnv } from './helpers/make-suite'; +// import { +// convertToCurrencyDecimals, +// buildFlashLiquidationAdapterParams, +// } from '../../helpers/contracts-helpers'; +// import { getMockUniswapRouter } from '../../helpers/contracts-getters'; +// import { deployFlashLiquidationAdapter } from '../../helpers/contracts-deployments'; +// import { MockUniswapV2Router02 } from '../../types/MockUniswapV2Router02'; +// import BigNumber from 'bignumber.js'; +// import { DRE, evmRevert, evmSnapshot, increaseTime, waitForTx } from '../../helpers/misc-utils'; +// import { ethers } from 'ethers'; +// import { ProtocolErrors, RateMode } from '../../helpers/types'; +// import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, oneEther } from '../../helpers/constants'; +// import { getUserData } from './helpers/utils/helpers'; +// import { calcExpectedStableDebtTokenBalance } from './helpers/utils/calculations'; +// const { expect } = require('chai'); + +// makeSuite('Uniswap adapters', (testEnv: TestEnv) => { +// let mockUniswapRouter: MockUniswapV2Router02; +// let evmSnapshotId: string; +// const { INVALID_HF, LP_LIQUIDATION_CALL_FAILED } = ProtocolErrors; + +// before(async () => { +// mockUniswapRouter = await getMockUniswapRouter(); +// }); + +// const depositAndHFBelowOne = async () => { +// const { dai, weth, users, pool, oracle } = testEnv; +// const depositor = users[0]; +// const borrower = users[1]; + +// //mints DAI to depositor +// await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + +// //approve protocol to access depositor wallet +// await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + +// //user 1 deposits 1000 DAI +// const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + +// await pool +// .connect(depositor.signer) +// .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); +// //user 2 deposits 1 ETH +// const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + +// //mints WETH to borrower +// await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); + +// //approve protocol to access the borrower wallet +// await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + +// await pool +// .connect(borrower.signer) +// .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + +// //user 2 borrows + +// const userGlobalDataBefore = await pool.getUserAccountData(borrower.address); +// const daiPrice = await oracle.getAssetPrice(dai.address); + +// const amountDAIToBorrow = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(userGlobalDataBefore.availableBorrowsETH.toString()) +// .div(daiPrice.toString()) +// .multipliedBy(0.95) +// .toFixed(0) +// ); + +// await pool +// .connect(borrower.signer) +// .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address); + +// const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + +// expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.equal( +// '8250', +// INVALID_HF +// ); + +// await oracle.setAssetPrice( +// dai.address, +// new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0) +// ); + +// const userGlobalData = await pool.getUserAccountData(borrower.address); + +// expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( +// oneEther.toFixed(0), +// INVALID_HF +// ); +// }; + +// const depositSameAssetAndHFBelowOne = async () => { +// const { dai, weth, users, pool, oracle } = testEnv; +// const depositor = users[0]; +// const borrower = users[1]; + +// //mints DAI to depositor +// await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + +// //approve protocol to access depositor wallet +// await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + +// //user 1 deposits 1000 DAI +// const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + +// await pool +// .connect(depositor.signer) +// .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); +// //user 2 deposits 1 ETH +// const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + +// //mints WETH to borrower +// await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); + +// //approve protocol to access the borrower wallet +// await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + +// await pool +// .connect(borrower.signer) +// .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + +// //user 2 borrows + +// const userGlobalDataBefore = await pool.getUserAccountData(borrower.address); +// const daiPrice = await oracle.getAssetPrice(dai.address); + +// const amountDAIToBorrow = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(userGlobalDataBefore.availableBorrowsETH.toString()) +// .div(daiPrice.toString()) +// .multipliedBy(0.8) +// .toFixed(0) +// ); +// await waitForTx( +// await pool +// .connect(borrower.signer) +// .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address) +// ); + +// const userGlobalDataBefore2 = await pool.getUserAccountData(borrower.address); + +// const amountWETHToBorrow = new BigNumber(userGlobalDataBefore2.availableBorrowsETH.toString()) +// .multipliedBy(0.8) +// .toFixed(0); + +// await pool +// .connect(borrower.signer) +// .borrow(weth.address, amountWETHToBorrow, RateMode.Variable, '0', borrower.address); + +// const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); + +// expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.equal( +// '8250', +// INVALID_HF +// ); + +// await oracle.setAssetPrice( +// dai.address, +// new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0) +// ); + +// const userGlobalData = await pool.getUserAccountData(borrower.address); + +// expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( +// oneEther.toFixed(0), +// INVALID_HF +// ); +// }; + +// beforeEach(async () => { +// evmSnapshotId = await evmSnapshot(); +// }); + +// afterEach(async () => { +// await evmRevert(evmSnapshotId); +// }); + +// describe('Flash Liquidation Adapter', () => { +// before('Before LendingPool liquidation: set config', () => { +// BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); +// }); + +// after('After LendingPool liquidation: reset config', () => { +// BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); +// }); + +// describe('constructor', () => { +// it('should deploy with correct parameters', async () => { +// const { addressesProvider, weth } = testEnv; +// await deployFlashLiquidationAdapter([ +// addressesProvider.address, +// mockUniswapRouter.address, +// weth.address, +// ]); +// }); + +// it('should revert if not valid addresses provider', async () => { +// const { weth } = testEnv; +// expect( +// deployFlashLiquidationAdapter([ +// mockUniswapRouter.address, +// mockUniswapRouter.address, +// weth.address, +// ]) +// ).to.be.reverted; +// }); +// }); + +// describe('executeOperation: succesfully liquidateCall and swap via Flash Loan with profits', () => { +// it('Liquidates the borrow with profit', async () => { +// await depositAndHFBelowOne(); +// await increaseTime(100); + +// const { +// dai, +// weth, +// users, +// pool, +// oracle, +// helpersContract, +// flashLiquidationAdapter, +// } = testEnv; + +// const liquidator = users[3]; +// const borrower = users[1]; +// const expectedSwap = ethers.utils.parseEther('0.4'); + +// const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); + +// // Set how much ETH will be sold and swapped for DAI at Uniswap mock +// await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); + +// const collateralPrice = await oracle.getAssetPrice(weth.address); +// const principalPrice = await oracle.getAssetPrice(dai.address); +// const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); +// const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); +// const userReserveDataBefore = await getUserData( +// pool, +// helpersContract, +// dai.address, +// borrower.address +// ); + +// const collateralDecimals = ( +// await helpersContract.getReserveConfigurationData(weth.address) +// ).decimals.toString(); +// const principalDecimals = ( +// await helpersContract.getReserveConfigurationData(dai.address) +// ).decimals.toString(); +// const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + +// const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) +// .times(new BigNumber(amountToLiquidate).times(105)) +// .times(new BigNumber(10).pow(collateralDecimals)) +// .div( +// new BigNumber(collateralPrice.toString()).times( +// new BigNumber(10).pow(principalDecimals) +// ) +// ) +// .div(100) +// .decimalPlaces(0, BigNumber.ROUND_DOWN); + +// const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) +// .multipliedBy(1.0009) +// .toFixed(0); + +// const expectedProfit = ethers.BigNumber.from(expectedCollateralLiquidated.toString()).sub( +// expectedSwap +// ); + +// const params = buildFlashLiquidationAdapterParams( +// weth.address, +// dai.address, +// borrower.address, +// amountToLiquidate, +// false +// ); +// const tx = await pool +// .connect(liquidator.signer) +// .flashLoan( +// flashLiquidationAdapter.address, +// [dai.address], +// [amountToLiquidate], +// [0], +// borrower.address, +// params, +// 0 +// ); + +// // Expect Swapped event +// await expect(Promise.resolve(tx)).to.emit(flashLiquidationAdapter, 'Swapped'); + +// // Expect LiquidationCall event +// await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); + +// const userReserveDataAfter = await getUserData( +// pool, +// helpersContract, +// dai.address, +// borrower.address +// ); +// const liquidatorWethBalanceAfter = await weth.balanceOf(liquidator.address); + +// const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); +// const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + +// if (!tx.blockNumber) { +// expect(false, 'Invalid block number'); +// return; +// } +// const txTimestamp = new BigNumber( +// (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp +// ); + +// const stableDebtBeforeTx = calcExpectedStableDebtTokenBalance( +// userReserveDataBefore.principalStableDebt, +// userReserveDataBefore.stableBorrowRate, +// userReserveDataBefore.stableRateLastUpdated, +// txTimestamp +// ); + +// const collateralAssetContractBalance = await weth.balanceOf( +// flashLiquidationAdapter.address +// ); +// const borrowAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); + +// expect(collateralAssetContractBalance).to.be.equal( +// '0', +// 'Contract address should not keep any balance.' +// ); +// expect(borrowAssetContractBalance).to.be.equal( +// '0', +// 'Contract address should not keep any balance.' +// ); + +// expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( +// stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), +// 'Invalid user debt after liquidation' +// ); + +// //the liquidity index of the principal reserve needs to be bigger than the index before +// expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( +// daiReserveDataBefore.liquidityIndex.toString(), +// 'Invalid liquidity index' +// ); + +// //the principal APY after a liquidation needs to be lower than the APY before +// expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( +// daiReserveDataBefore.liquidityRate.toString(), +// 'Invalid liquidity APY' +// ); + +// expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( +// new BigNumber(daiReserveDataBefore.availableLiquidity.toString()) +// .plus(flashLoanDebt) +// .toFixed(0), +// 'Invalid principal available liquidity' +// ); + +// expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( +// new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) +// .minus(expectedCollateralLiquidated) +// .toFixed(0), +// 'Invalid collateral available liquidity' +// ); + +// // Profit after flash loan liquidation +// expect(liquidatorWethBalanceAfter).to.be.equal( +// liquidatorWethBalanceBefore.add(expectedProfit), +// 'Invalid expected WETH profit' +// ); +// }); +// }); + +// describe('executeOperation: succesfully liquidateCall with same asset via Flash Loan, but no swap needed', () => { +// it('Liquidates the borrow with profit', async () => { +// await depositSameAssetAndHFBelowOne(); +// await increaseTime(100); + +// const { weth, users, pool, oracle, helpersContract, flashLiquidationAdapter } = testEnv; + +// const liquidator = users[3]; +// const borrower = users[1]; + +// const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); + +// const assetPrice = await oracle.getAssetPrice(weth.address); +// const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); +// const userReserveDataBefore = await getUserData( +// pool, +// helpersContract, +// weth.address, +// borrower.address +// ); + +// const assetDecimals = ( +// await helpersContract.getReserveConfigurationData(weth.address) +// ).decimals.toString(); +// const amountToLiquidate = userReserveDataBefore.currentVariableDebt.div(2).toFixed(0); + +// const expectedCollateralLiquidated = new BigNumber(assetPrice.toString()) +// .times(new BigNumber(amountToLiquidate).times(105)) +// .times(new BigNumber(10).pow(assetDecimals)) +// .div(new BigNumber(assetPrice.toString()).times(new BigNumber(10).pow(assetDecimals))) +// .div(100) +// .decimalPlaces(0, BigNumber.ROUND_DOWN); + +// const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) +// .multipliedBy(1.0009) +// .toFixed(0); + +// const params = buildFlashLiquidationAdapterParams( +// weth.address, +// weth.address, +// borrower.address, +// amountToLiquidate, +// false +// ); +// const tx = await pool +// .connect(liquidator.signer) +// .flashLoan( +// flashLiquidationAdapter.address, +// [weth.address], +// [amountToLiquidate], +// [0], +// borrower.address, +// params, +// 0 +// ); + +// // Dont expect Swapped event due is same asset +// await expect(Promise.resolve(tx)).to.not.emit(flashLiquidationAdapter, 'Swapped'); + +// // Expect LiquidationCall event +// await expect(Promise.resolve(tx)) +// .to.emit(pool, 'LiquidationCall') +// .withArgs( +// weth.address, +// weth.address, +// borrower.address, +// amountToLiquidate.toString(), +// expectedCollateralLiquidated.toString(), +// flashLiquidationAdapter.address, +// false +// ); + +// const borrowAssetContractBalance = await weth.balanceOf(flashLiquidationAdapter.address); + +// expect(borrowAssetContractBalance).to.be.equal( +// '0', +// 'Contract address should not keep any balance.' +// ); +// }); +// }); + +// describe('executeOperation: succesfully liquidateCall and swap via Flash Loan without profits', () => { +// it('Liquidates the borrow', async () => { +// await depositAndHFBelowOne(); +// await increaseTime(100); + +// const { +// dai, +// weth, +// users, +// pool, +// oracle, +// helpersContract, +// flashLiquidationAdapter, +// } = testEnv; + +// const liquidator = users[3]; +// const borrower = users[1]; +// const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); + +// const collateralPrice = await oracle.getAssetPrice(weth.address); +// const principalPrice = await oracle.getAssetPrice(dai.address); +// const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); +// const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); +// const userReserveDataBefore = await getUserData( +// pool, +// helpersContract, +// dai.address, +// borrower.address +// ); + +// const collateralDecimals = ( +// await helpersContract.getReserveConfigurationData(weth.address) +// ).decimals.toString(); +// const principalDecimals = ( +// await helpersContract.getReserveConfigurationData(dai.address) +// ).decimals.toString(); +// const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + +// const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) +// .times(new BigNumber(amountToLiquidate).times(105)) +// .times(new BigNumber(10).pow(collateralDecimals)) +// .div( +// new BigNumber(collateralPrice.toString()).times( +// new BigNumber(10).pow(principalDecimals) +// ) +// ) +// .div(100) +// .decimalPlaces(0, BigNumber.ROUND_DOWN); + +// const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) +// .multipliedBy(1.0009) +// .toFixed(0); + +// // Set how much ETH will be sold and swapped for DAI at Uniswap mock +// await ( +// await mockUniswapRouter.setAmountToSwap( +// weth.address, +// expectedCollateralLiquidated.toString() +// ) +// ).wait(); + +// const params = buildFlashLiquidationAdapterParams( +// weth.address, +// dai.address, +// borrower.address, +// amountToLiquidate, +// false +// ); +// const tx = await pool +// .connect(liquidator.signer) +// .flashLoan( +// flashLiquidationAdapter.address, +// [dai.address], +// [flashLoanDebt], +// [0], +// borrower.address, +// params, +// 0 +// ); + +// // Expect Swapped event +// await expect(Promise.resolve(tx)).to.emit(flashLiquidationAdapter, 'Swapped'); + +// // Expect LiquidationCall event +// await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); + +// const userReserveDataAfter = await getUserData( +// pool, +// helpersContract, +// dai.address, +// borrower.address +// ); +// const liquidatorWethBalanceAfter = await weth.balanceOf(liquidator.address); + +// const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); +// const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); + +// if (!tx.blockNumber) { +// expect(false, 'Invalid block number'); +// return; +// } +// const txTimestamp = new BigNumber( +// (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp +// ); + +// const stableDebtBeforeTx = calcExpectedStableDebtTokenBalance( +// userReserveDataBefore.principalStableDebt, +// userReserveDataBefore.stableBorrowRate, +// userReserveDataBefore.stableRateLastUpdated, +// txTimestamp +// ); + +// const collateralAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); +// const borrowAssetContractBalance = await weth.balanceOf(flashLiquidationAdapter.address); + +// expect(collateralAssetContractBalance).to.be.equal( +// '0', +// 'Contract address should not keep any balance.' +// ); +// expect(borrowAssetContractBalance).to.be.equal( +// '0', +// 'Contract address should not keep any balance.' +// ); +// expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( +// stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), +// 'Invalid user debt after liquidation' +// ); + +// //the liquidity index of the principal reserve needs to be bigger than the index before +// expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( +// daiReserveDataBefore.liquidityIndex.toString(), +// 'Invalid liquidity index' +// ); + +// //the principal APY after a liquidation needs to be lower than the APY before +// expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( +// daiReserveDataBefore.liquidityRate.toString(), +// 'Invalid liquidity APY' +// ); + +// expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( +// new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) +// .minus(expectedCollateralLiquidated) +// .toFixed(0), +// 'Invalid collateral available liquidity' +// ); + +// // Net Profit == 0 after flash loan liquidation +// expect(liquidatorWethBalanceAfter).to.be.equal( +// liquidatorWethBalanceBefore, +// 'Invalid expected WETH profit' +// ); +// }); +// }); + +// describe('executeOperation: succesfully liquidateCall all available debt and swap via Flash Loan ', () => { +// it('Liquidates the borrow', async () => { +// await depositAndHFBelowOne(); +// await increaseTime(100); + +// const { +// dai, +// weth, +// users, +// pool, +// oracle, +// helpersContract, +// flashLiquidationAdapter, +// } = testEnv; + +// const liquidator = users[3]; +// const borrower = users[1]; +// const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); + +// const collateralPrice = await oracle.getAssetPrice(weth.address); +// const principalPrice = await oracle.getAssetPrice(dai.address); +// const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); +// const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); +// const userReserveDataBefore = await getUserData( +// pool, +// helpersContract, +// dai.address, +// borrower.address +// ); + +// const collateralDecimals = ( +// await helpersContract.getReserveConfigurationData(weth.address) +// ).decimals.toString(); +// const principalDecimals = ( +// await helpersContract.getReserveConfigurationData(dai.address) +// ).decimals.toString(); +// const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); +// const extraAmount = new BigNumber(amountToLiquidate).times('1.15').toFixed(0); + +// const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) +// .times(new BigNumber(amountToLiquidate).times(105)) +// .times(new BigNumber(10).pow(collateralDecimals)) +// .div( +// new BigNumber(collateralPrice.toString()).times( +// new BigNumber(10).pow(principalDecimals) +// ) +// ) +// .div(100) +// .decimalPlaces(0, BigNumber.ROUND_DOWN); + +// const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) +// .multipliedBy(1.0009) +// .toFixed(0); + +// // Set how much ETH will be sold and swapped for DAI at Uniswap mock +// await ( +// await mockUniswapRouter.setAmountToSwap( +// weth.address, +// expectedCollateralLiquidated.toString() +// ) +// ).wait(); + +// const params = buildFlashLiquidationAdapterParams( +// weth.address, +// dai.address, +// borrower.address, +// MAX_UINT_AMOUNT, +// false +// ); +// const tx = await pool +// .connect(liquidator.signer) +// .flashLoan( +// flashLiquidationAdapter.address, +// [dai.address], +// [extraAmount], +// [0], +// borrower.address, +// params, +// 0 +// ); + +// // Expect Swapped event +// await expect(Promise.resolve(tx)).to.emit(flashLiquidationAdapter, 'Swapped'); + +// // Expect LiquidationCall event +// await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); + +// const collateralAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); +// const borrowAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); + +// expect(collateralAssetContractBalance).to.be.equal( +// '0', +// 'Contract address should not keep any balance.' +// ); +// expect(borrowAssetContractBalance).to.be.equal( +// '0', +// 'Contract address should not keep any balance.' +// ); +// }); +// }); + +// describe('executeOperation: invalid params', async () => { +// it('Revert if debt asset is different than requested flash loan token', async () => { +// await depositAndHFBelowOne(); + +// const { dai, weth, users, pool, helpersContract, flashLiquidationAdapter } = testEnv; + +// const liquidator = users[3]; +// const borrower = users[1]; +// const expectedSwap = ethers.utils.parseEther('0.4'); + +// // Set how much ETH will be sold and swapped for DAI at Uniswap mock +// await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); + +// const userReserveDataBefore = await getUserData( +// pool, +// helpersContract, +// dai.address, +// borrower.address +// ); + +// const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + +// // Wrong debt asset +// const params = buildFlashLiquidationAdapterParams( +// weth.address, +// weth.address, // intentionally bad +// borrower.address, +// amountToLiquidate, +// false +// ); +// await expect( +// pool +// .connect(liquidator.signer) +// .flashLoan( +// flashLiquidationAdapter.address, +// [dai.address], +// [amountToLiquidate], +// [0], +// borrower.address, +// params, +// 0 +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); +// }); + +// it('Revert if debt asset amount to liquidate is greater than requested flash loan', async () => { +// await depositAndHFBelowOne(); + +// const { dai, weth, users, pool, helpersContract, flashLiquidationAdapter } = testEnv; + +// const liquidator = users[3]; +// const borrower = users[1]; +// const expectedSwap = ethers.utils.parseEther('0.4'); + +// // Set how much ETH will be sold and swapped for DAI at Uniswap mock +// await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); + +// const userReserveDataBefore = await getUserData( +// pool, +// helpersContract, +// dai.address, +// borrower.address +// ); + +// const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2); + +// // Correct params +// const params = buildFlashLiquidationAdapterParams( +// weth.address, +// dai.address, +// borrower.address, +// amountToLiquidate.toString(), +// false +// ); +// // Bad flash loan params: requested DAI amount below amountToLiquidate +// await expect( +// pool +// .connect(liquidator.signer) +// .flashLoan( +// flashLiquidationAdapter.address, +// [dai.address], +// [amountToLiquidate.div(2).toString()], +// [0], +// borrower.address, +// params, +// 0 +// ) +// ).to.be.revertedWith(LP_LIQUIDATION_CALL_FAILED); +// }); + +// it('Revert if requested multiple assets', async () => { +// await depositAndHFBelowOne(); + +// const { dai, weth, users, pool, helpersContract, flashLiquidationAdapter } = testEnv; + +// const liquidator = users[3]; +// const borrower = users[1]; +// const expectedSwap = ethers.utils.parseEther('0.4'); + +// // Set how much ETH will be sold and swapped for DAI at Uniswap mock +// await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); + +// const userReserveDataBefore = await getUserData( +// pool, +// helpersContract, +// dai.address, +// borrower.address +// ); + +// const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2); + +// // Correct params +// const params = buildFlashLiquidationAdapterParams( +// weth.address, +// dai.address, +// borrower.address, +// amountToLiquidate.toString(), +// false +// ); +// // Bad flash loan params: requested multiple assets +// await expect( +// pool +// .connect(liquidator.signer) +// .flashLoan( +// flashLiquidationAdapter.address, +// [dai.address, weth.address], +// [10, 10], +// [0], +// borrower.address, +// params, +// 0 +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); +// }); +// }); +// }); +// }); diff --git a/test-suites/test-lp/uniswapAdapters.liquiditySwap.spec.ts b/test-suites/test-lp/uniswapAdapters.liquiditySwap.spec.ts new file mode 100644 index 00000000..30631f3e --- /dev/null +++ b/test-suites/test-lp/uniswapAdapters.liquiditySwap.spec.ts @@ -0,0 +1,1854 @@ +// import { makeSuite, TestEnv } from './helpers/make-suite'; +// import { +// convertToCurrencyDecimals, +// getContract, +// buildPermitParams, +// getSignatureFromTypedData, +// buildLiquiditySwapParams, +// } from '../../helpers/contracts-helpers'; +// import { getMockUniswapRouter } from '../../helpers/contracts-getters'; +// import { deployUniswapLiquiditySwapAdapter } from '../../helpers/contracts-deployments'; +// import { MockUniswapV2Router02 } from '../../types/MockUniswapV2Router02'; +// import { Zero } from '@ethersproject/constants'; +// import BigNumber from 'bignumber.js'; +// import { DRE, evmRevert, evmSnapshot } from '../../helpers/misc-utils'; +// import { ethers } from 'ethers'; +// import { eContractid } from '../../helpers/types'; +// import { AToken } from '../../types/AToken'; +// import { BUIDLEREVM_CHAINID } from '../../helpers/buidler-constants'; +// import { MAX_UINT_AMOUNT } from '../../helpers/constants'; +// const { parseEther } = ethers.utils; + +// const { expect } = require('chai'); + +// makeSuite('Uniswap adapters', (testEnv: TestEnv) => { +// let mockUniswapRouter: MockUniswapV2Router02; +// let evmSnapshotId: string; + +// before(async () => { +// mockUniswapRouter = await getMockUniswapRouter(); +// }); + +// beforeEach(async () => { +// evmSnapshotId = await evmSnapshot(); +// }); + +// afterEach(async () => { +// await evmRevert(evmSnapshotId); +// }); + +// describe('UniswapLiquiditySwapAdapter', () => { +// describe('constructor', () => { +// it('should deploy with correct parameters', async () => { +// const { addressesProvider, weth } = testEnv; +// await deployUniswapLiquiditySwapAdapter([ +// addressesProvider.address, +// mockUniswapRouter.address, +// weth.address, +// ]); +// }); + +// it('should revert if not valid addresses provider', async () => { +// const { weth } = testEnv; +// expect( +// deployUniswapLiquiditySwapAdapter([ +// mockUniswapRouter.address, +// mockUniswapRouter.address, +// weth.address, +// ]) +// ).to.be.reverted; +// }); +// }); + +// describe('executeOperation', () => { +// beforeEach(async () => { +// const { users, weth, dai, usdc, pool, deployer } = testEnv; +// const userAddress = users[0].address; + +// // Provide liquidity +// await dai.mint(parseEther('20000')); +// await dai.approve(pool.address, parseEther('20000')); +// await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); + +// const usdcAmount = await convertToCurrencyDecimals(usdc.address, '10'); +// await usdc.mint(usdcAmount); +// await usdc.approve(pool.address, usdcAmount); +// await pool.deposit(usdc.address, usdcAmount, deployer.address, 0); + +// // Make a deposit for user +// await weth.mint(parseEther('100')); +// await weth.approve(pool.address, parseEther('100')); +// await pool.deposit(weth.address, parseEther('100'), userAddress, 0); +// }); + +// it('should correctly swap tokens and deposit the out tokens in the pool', async () => { +// const { +// users, +// weth, +// oracle, +// dai, +// aDai, +// aWETH, +// pool, +// uniswapLiquiditySwapAdapter, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + +// // User will swap liquidity 10 aEth to aDai +// const liquidityToSwap = parseEther('10'); +// await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// // Subtract the FL fee from the amount to be swapped 0,09% +// const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); + +// const params = buildLiquiditySwapParams( +// [dai.address], +// [expectedDaiAmount], +// [0], +// [0], +// [0], +// [0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ) +// .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') +// .withArgs(weth.address, dai.address, flashloanAmount.toString(), expectedDaiAmount); + +// const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(userADaiBalance).to.be.eq(expectedDaiAmount); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); +// }); + +// it('should correctly swap and deposit multiple tokens', async () => { +// const { +// users, +// weth, +// oracle, +// dai, +// aDai, +// aWETH, +// usdc, +// pool, +// uniswapLiquiditySwapAdapter, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmountForEth = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); +// const usdcPrice = await oracle.getAssetPrice(usdc.address); + +// const collateralDecimals = (await usdc.decimals()).toString(); +// const principalDecimals = (await dai.decimals()).toString(); + +// const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountUSDCtoSwap.toString()) +// .times( +// new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) +// ) +// .div( +// new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) +// ) +// .toFixed(0) +// ); + +// // Make a deposit for user +// await usdc.connect(user).mint(amountUSDCtoSwap); +// await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); +// await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + +// const aUsdcData = await pool.getReserveData(usdc.address); +// const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); +// await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); + +// await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountWETHtoSwap); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); +// await aUsdc.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountUSDCtoSwap); +// const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); + +// // Subtract the FL fee from the amount to be swapped 0,09% +// const wethFlashloanAmount = new BigNumber(amountWETHtoSwap.toString()) +// .div(1.0009) +// .toFixed(0); +// const usdcFlashloanAmount = new BigNumber(amountUSDCtoSwap.toString()) +// .div(1.0009) +// .toFixed(0); + +// const params = buildLiquiditySwapParams( +// [dai.address, dai.address], +// [expectedDaiAmountForEth, expectedDaiAmountForUsdc], +// [0, 0], +// [0, 0], +// [0, 0], +// [0, 0], +// [ +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// ], +// [ +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// ], +// [false, false] +// ); + +// await pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address, usdc.address], +// [wethFlashloanAmount.toString(), usdcFlashloanAmount.toString()], +// [0, 0], +// userAddress, +// params, +// 0 +// ); + +// const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const userAUsdcBalance = await aUsdc.balanceOf(userAddress); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); +// expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); +// expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); +// }); + +// it('should correctly swap and deposit multiple tokens using permit', async () => { +// const { +// users, +// weth, +// oracle, +// dai, +// aDai, +// aWETH, +// usdc, +// pool, +// uniswapLiquiditySwapAdapter, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; +// const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; +// const deadline = MAX_UINT_AMOUNT; + +// const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; +// if (!ownerPrivateKey) { +// throw new Error('INVALID_OWNER_PK'); +// } + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmountForEth = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); +// const usdcPrice = await oracle.getAssetPrice(usdc.address); + +// const collateralDecimals = (await usdc.decimals()).toString(); +// const principalDecimals = (await dai.decimals()).toString(); + +// const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountUSDCtoSwap.toString()) +// .times( +// new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) +// ) +// .div( +// new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) +// ) +// .toFixed(0) +// ); + +// // Make a deposit for user +// await usdc.connect(user).mint(amountUSDCtoSwap); +// await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); +// await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + +// const aUsdcData = await pool.getReserveData(usdc.address); +// const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); +// await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); + +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); +// const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); + +// const wethFlashloanAmount = new BigNumber(amountWETHtoSwap.toString()) +// .div(1.0009) +// .toFixed(0); + +// const usdcFlashloanAmount = new BigNumber(amountUSDCtoSwap.toString()) +// .div(1.0009) +// .toFixed(0); + +// const aWethNonce = (await aWETH._nonces(userAddress)).toNumber(); +// const aWethMsgParams = buildPermitParams( +// chainId, +// aWETH.address, +// '1', +// await aWETH.name(), +// userAddress, +// uniswapLiquiditySwapAdapter.address, +// aWethNonce, +// deadline, +// amountWETHtoSwap.toString() +// ); +// const { v: aWETHv, r: aWETHr, s: aWETHs } = getSignatureFromTypedData( +// ownerPrivateKey, +// aWethMsgParams +// ); + +// const aUsdcNonce = (await aUsdc._nonces(userAddress)).toNumber(); +// const aUsdcMsgParams = buildPermitParams( +// chainId, +// aUsdc.address, +// '1', +// await aUsdc.name(), +// userAddress, +// uniswapLiquiditySwapAdapter.address, +// aUsdcNonce, +// deadline, +// amountUSDCtoSwap.toString() +// ); +// const { v: aUsdcv, r: aUsdcr, s: aUsdcs } = getSignatureFromTypedData( +// ownerPrivateKey, +// aUsdcMsgParams +// ); +// const params = buildLiquiditySwapParams( +// [dai.address, dai.address], +// [expectedDaiAmountForEth, expectedDaiAmountForUsdc], +// [0, 0], +// [amountWETHtoSwap, amountUSDCtoSwap], +// [deadline, deadline], +// [aWETHv, aUsdcv], +// [aWETHr, aUsdcr], +// [aWETHs, aUsdcs], +// [false, false] +// ); + +// await pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address, usdc.address], +// [wethFlashloanAmount.toString(), usdcFlashloanAmount.toString()], +// [0, 0], +// userAddress, +// params, +// 0 +// ); + +// const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const userAUsdcBalance = await aUsdc.balanceOf(userAddress); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); +// expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); +// expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); +// }); + +// it('should correctly swap tokens with permit', async () => { +// const { +// users, +// weth, +// oracle, +// dai, +// aDai, +// aWETH, +// pool, +// uniswapLiquiditySwapAdapter, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + +// // User will swap liquidity 10 aEth to aDai +// const liquidityToSwap = parseEther('10'); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// // Subtract the FL fee from the amount to be swapped 0,09% +// const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); + +// const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; +// const deadline = MAX_UINT_AMOUNT; +// const nonce = (await aWETH._nonces(userAddress)).toNumber(); +// const msgParams = buildPermitParams( +// chainId, +// aWETH.address, +// '1', +// await aWETH.name(), +// userAddress, +// uniswapLiquiditySwapAdapter.address, +// nonce, +// deadline, +// liquidityToSwap.toString() +// ); + +// const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; +// if (!ownerPrivateKey) { +// throw new Error('INVALID_OWNER_PK'); +// } + +// const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + +// const params = buildLiquiditySwapParams( +// [dai.address], +// [expectedDaiAmount], +// [0], +// [liquidityToSwap], +// [deadline], +// [v], +// [r], +// [s], +// [false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ) +// .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') +// .withArgs(weth.address, dai.address, flashloanAmount.toString(), expectedDaiAmount); + +// const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(userADaiBalance).to.be.eq(expectedDaiAmount); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); +// }); + +// it('should revert if inconsistent params', async () => { +// const { users, weth, oracle, dai, aWETH, pool, uniswapLiquiditySwapAdapter } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + +// // User will swap liquidity 10 aEth to aDai +// const liquidityToSwap = parseEther('10'); +// await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + +// // Subtract the FL fee from the amount to be swapped 0,09% +// const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); + +// const params = buildLiquiditySwapParams( +// [dai.address, weth.address], +// [expectedDaiAmount], +// [0], +// [0], +// [0], +// [0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); + +// const params2 = buildLiquiditySwapParams( +// [dai.address, weth.address], +// [expectedDaiAmount], +// [0, 0], +// [0, 0], +// [0, 0], +// [0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params2, +// 0 +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); + +// const params3 = buildLiquiditySwapParams( +// [dai.address, weth.address], +// [expectedDaiAmount], +// [0, 0], +// [0], +// [0, 0], +// [0, 0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params3, +// 0 +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); + +// const params4 = buildLiquiditySwapParams( +// [dai.address, weth.address], +// [expectedDaiAmount], +// [0], +// [0], +// [0], +// [0], +// [ +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// ], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params4, +// 0 +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); + +// const params5 = buildLiquiditySwapParams( +// [dai.address, weth.address], +// [expectedDaiAmount], +// [0], +// [0], +// [0], +// [0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [ +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// ], +// [false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params5, +// 0 +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); + +// const params6 = buildLiquiditySwapParams( +// [dai.address, weth.address], +// [expectedDaiAmount, expectedDaiAmount], +// [0], +// [0], +// [0], +// [0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params6, +// 0 +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); + +// const params7 = buildLiquiditySwapParams( +// [dai.address], +// [expectedDaiAmount], +// [0, 0], +// [0], +// [0], +// [0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params7, +// 0 +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); + +// const params8 = buildLiquiditySwapParams( +// [dai.address], +// [expectedDaiAmount], +// [0], +// [0, 0], +// [0], +// [0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params8, +// 0 +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); + +// const params9 = buildLiquiditySwapParams( +// [dai.address], +// [expectedDaiAmount], +// [0], +// [0], +// [0], +// [0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false, false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params9, +// 0 +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); +// }); + +// it('should revert if caller not lending pool', async () => { +// const { users, weth, oracle, dai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + +// // User will swap liquidity 10 aEth to aDai +// const liquidityToSwap = parseEther('10'); +// await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + +// // Subtract the FL fee from the amount to be swapped 0,09% +// const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); + +// const params = buildLiquiditySwapParams( +// [dai.address], +// [expectedDaiAmount], +// [0], +// [0], +// [0], +// [0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false] +// ); + +// await expect( +// uniswapLiquiditySwapAdapter +// .connect(user) +// .executeOperation( +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params +// ) +// ).to.be.revertedWith('CALLER_MUST_BE_LENDING_POOL'); +// }); + +// it('should work correctly with tokens of different decimals', async () => { +// const { +// users, +// usdc, +// oracle, +// dai, +// aDai, +// uniswapLiquiditySwapAdapter, +// pool, +// deployer, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); +// const liquidity = await convertToCurrencyDecimals(usdc.address, '20000'); + +// // Provide liquidity +// await usdc.mint(liquidity); +// await usdc.approve(pool.address, liquidity); +// await pool.deposit(usdc.address, liquidity, deployer.address, 0); + +// // Make a deposit for user +// await usdc.connect(user).mint(amountUSDCtoSwap); +// await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); +// await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + +// const usdcPrice = await oracle.getAssetPrice(usdc.address); +// const daiPrice = await oracle.getAssetPrice(dai.address); + +// // usdc 6 +// const collateralDecimals = (await usdc.decimals()).toString(); +// const principalDecimals = (await dai.decimals()).toString(); + +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountUSDCtoSwap.toString()) +// .times( +// new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) +// ) +// .div( +// new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) +// ) +// .toFixed(0) +// ); + +// await mockUniswapRouter.connect(user).setAmountToReturn(usdc.address, expectedDaiAmount); + +// const aUsdcData = await pool.getReserveData(usdc.address); +// const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); +// const aUsdcBalance = await aUsdc.balanceOf(userAddress); +// await aUsdc.connect(user).approve(uniswapLiquiditySwapAdapter.address, aUsdcBalance); +// // Subtract the FL fee from the amount to be swapped 0,09% +// const flashloanAmount = new BigNumber(amountUSDCtoSwap.toString()).div(1.0009).toFixed(0); + +// const params = buildLiquiditySwapParams( +// [dai.address], +// [expectedDaiAmount], +// [0], +// [0], +// [0], +// [0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [usdc.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ) +// .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') +// .withArgs(usdc.address, dai.address, flashloanAmount.toString(), expectedDaiAmount); + +// const adapterUsdcBalance = await usdc.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const aDaiBalance = await aDai.balanceOf(userAddress); + +// expect(adapterUsdcBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(aDaiBalance).to.be.eq(expectedDaiAmount); +// }); + +// it('should revert when min amount to receive exceeds the max slippage amount', async () => { +// const { users, weth, oracle, dai, aWETH, pool, uniswapLiquiditySwapAdapter } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); +// const smallExpectedDaiAmount = expectedDaiAmount.div(2); + +// // User will swap liquidity 10 aEth to aDai +// const liquidityToSwap = parseEther('10'); +// await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + +// // Subtract the FL fee from the amount to be swapped 0,09% +// const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); + +// const params = buildLiquiditySwapParams( +// [dai.address], +// [smallExpectedDaiAmount], +// [0], +// [0], +// [0], +// [0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false] +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [flashloanAmount.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ).to.be.revertedWith('minAmountOut exceed max slippage'); +// }); + +// it('should correctly swap tokens all the balance', async () => { +// const { +// users, +// weth, +// oracle, +// dai, +// aDai, +// aWETH, +// pool, +// uniswapLiquiditySwapAdapter, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + +// // Remove other balance +// await aWETH.connect(user).transfer(users[1].address, parseEther('90')); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// // User will swap liquidity 10 aEth to aDai +// const liquidityToSwap = parseEther('10'); +// expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); +// await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + +// const params = buildLiquiditySwapParams( +// [dai.address], +// [expectedDaiAmount], +// [1], +// [0], +// [0], +// [0], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// ['0x0000000000000000000000000000000000000000000000000000000000000000'], +// [false] +// ); + +// // Flashloan + premium > aToken balance. Then it will only swap the balance - premium +// const flashloanFee = liquidityToSwap.mul(9).div(10000); +// const swappedAmount = liquidityToSwap.sub(flashloanFee); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [liquidityToSwap.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ) +// .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') +// .withArgs(weth.address, dai.address, swappedAmount.toString(), expectedDaiAmount); + +// const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(userADaiBalance).to.be.eq(expectedDaiAmount); +// expect(userAEthBalance).to.be.eq(Zero); +// expect(adapterAEthBalance).to.be.eq(Zero); +// }); + +// it('should correctly swap tokens all the balance using permit', async () => { +// const { +// users, +// weth, +// oracle, +// dai, +// aDai, +// aWETH, +// pool, +// uniswapLiquiditySwapAdapter, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + +// // Remove other balance +// await aWETH.connect(user).transfer(users[1].address, parseEther('90')); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// const liquidityToSwap = parseEther('10'); +// expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); + +// const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; +// const deadline = MAX_UINT_AMOUNT; +// const nonce = (await aWETH._nonces(userAddress)).toNumber(); +// const msgParams = buildPermitParams( +// chainId, +// aWETH.address, +// '1', +// await aWETH.name(), +// userAddress, +// uniswapLiquiditySwapAdapter.address, +// nonce, +// deadline, +// liquidityToSwap.toString() +// ); + +// const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; +// if (!ownerPrivateKey) { +// throw new Error('INVALID_OWNER_PK'); +// } + +// const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + +// const params = buildLiquiditySwapParams( +// [dai.address], +// [expectedDaiAmount], +// [1], +// [liquidityToSwap], +// [deadline], +// [v], +// [r], +// [s], +// [false] +// ); + +// // Flashloan + premium > aToken balance. Then it will only swap the balance - premium +// const flashloanFee = liquidityToSwap.mul(9).div(10000); +// const swappedAmount = liquidityToSwap.sub(flashloanFee); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapLiquiditySwapAdapter.address, +// [weth.address], +// [liquidityToSwap.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ) +// .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') +// .withArgs(weth.address, dai.address, swappedAmount.toString(), expectedDaiAmount); + +// const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(userADaiBalance).to.be.eq(expectedDaiAmount); +// expect(userAEthBalance).to.be.eq(Zero); +// expect(adapterAEthBalance).to.be.eq(Zero); +// }); +// }); + +// describe('swapAndDeposit', () => { +// beforeEach(async () => { +// const { users, weth, dai, pool, deployer } = testEnv; +// const userAddress = users[0].address; + +// // Provide liquidity +// await dai.mint(parseEther('20000')); +// await dai.approve(pool.address, parseEther('20000')); +// await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); + +// // Make a deposit for user +// await weth.mint(parseEther('100')); +// await weth.approve(pool.address, parseEther('100')); +// await pool.deposit(weth.address, parseEther('100'), userAddress, 0); +// }); + +// it('should correctly swap tokens and deposit the out tokens in the pool', async () => { +// const { users, weth, oracle, dai, aDai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + +// // User will swap liquidity 10 aEth to aDai +// const liquidityToSwap = parseEther('10'); +// await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// await expect( +// uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( +// [weth.address], +// [dai.address], +// [amountWETHtoSwap], +// [expectedDaiAmount], +// [ +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// ], +// [false] +// ) +// ) +// .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') +// .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); + +// const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(userADaiBalance).to.be.eq(expectedDaiAmount); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); +// }); + +// it('should correctly swap tokens using permit', async () => { +// const { users, weth, oracle, dai, aDai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + +// // User will swap liquidity 10 aEth to aDai +// const liquidityToSwap = parseEther('10'); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; +// const deadline = MAX_UINT_AMOUNT; +// const nonce = (await aWETH._nonces(userAddress)).toNumber(); +// const msgParams = buildPermitParams( +// chainId, +// aWETH.address, +// '1', +// await aWETH.name(), +// userAddress, +// uniswapLiquiditySwapAdapter.address, +// nonce, +// deadline, +// liquidityToSwap.toString() +// ); + +// const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; +// if (!ownerPrivateKey) { +// throw new Error('INVALID_OWNER_PK'); +// } + +// const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + +// await expect( +// uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( +// [weth.address], +// [dai.address], +// [amountWETHtoSwap], +// [expectedDaiAmount], +// [ +// { +// amount: liquidityToSwap, +// deadline, +// v, +// r, +// s, +// }, +// ], +// [false] +// ) +// ) +// .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') +// .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); + +// const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(userADaiBalance).to.be.eq(expectedDaiAmount); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); +// }); + +// it('should revert if inconsistent params', async () => { +// const { users, weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv; +// const user = users[0].signer; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await expect( +// uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( +// [weth.address, dai.address], +// [dai.address], +// [amountWETHtoSwap], +// [expectedDaiAmount], +// [ +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// ], +// [false] +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); + +// await expect( +// uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( +// [weth.address], +// [dai.address, weth.address], +// [amountWETHtoSwap], +// [expectedDaiAmount], +// [ +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// ], +// [false] +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); + +// await expect( +// uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( +// [weth.address], +// [dai.address], +// [amountWETHtoSwap, amountWETHtoSwap], +// [expectedDaiAmount], +// [ +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// ], +// [false] +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); + +// await expect( +// uniswapLiquiditySwapAdapter +// .connect(user) +// .swapAndDeposit( +// [weth.address], +// [dai.address], +// [amountWETHtoSwap], +// [expectedDaiAmount], +// [], +// [false] +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); + +// await expect( +// uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( +// [weth.address], +// [dai.address], +// [amountWETHtoSwap], +// [expectedDaiAmount, expectedDaiAmount], +// [ +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// ], +// [false] +// ) +// ).to.be.revertedWith('INCONSISTENT_PARAMS'); +// }); + +// it('should revert when min amount to receive exceeds the max slippage amount', async () => { +// const { users, weth, oracle, dai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; +// const user = users[0].signer; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); +// const smallExpectedDaiAmount = expectedDaiAmount.div(2); + +// // User will swap liquidity 10 aEth to aDai +// const liquidityToSwap = parseEther('10'); +// await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + +// await expect( +// uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( +// [weth.address], +// [dai.address], +// [amountWETHtoSwap], +// [smallExpectedDaiAmount], +// [ +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// ], +// [false] +// ) +// ).to.be.revertedWith('minAmountOut exceed max slippage'); +// }); + +// it('should correctly swap tokens and deposit multiple tokens', async () => { +// const { +// users, +// weth, +// usdc, +// oracle, +// dai, +// aDai, +// aWETH, +// uniswapLiquiditySwapAdapter, +// pool, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmountForEth = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); +// const usdcPrice = await oracle.getAssetPrice(usdc.address); + +// const collateralDecimals = (await usdc.decimals()).toString(); +// const principalDecimals = (await dai.decimals()).toString(); + +// const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountUSDCtoSwap.toString()) +// .times( +// new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) +// ) +// .div( +// new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) +// ) +// .toFixed(0) +// ); + +// // Make a deposit for user +// await usdc.connect(user).mint(amountUSDCtoSwap); +// await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); +// await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + +// const aUsdcData = await pool.getReserveData(usdc.address); +// const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); +// await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); + +// await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountWETHtoSwap); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); +// await aUsdc.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountUSDCtoSwap); +// const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); + +// await uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( +// [weth.address, usdc.address], +// [dai.address, dai.address], +// [amountWETHtoSwap, amountUSDCtoSwap], +// [expectedDaiAmountForEth, expectedDaiAmountForUsdc], +// [ +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// ], +// [false, false] +// ); + +// const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const userAUsdcBalance = await aUsdc.balanceOf(userAddress); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); +// expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); +// expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); +// }); + +// it('should correctly swap tokens and deposit multiple tokens using permit', async () => { +// const { +// users, +// weth, +// usdc, +// oracle, +// dai, +// aDai, +// aWETH, +// uniswapLiquiditySwapAdapter, +// pool, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; +// const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; +// const deadline = MAX_UINT_AMOUNT; + +// const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; +// if (!ownerPrivateKey) { +// throw new Error('INVALID_OWNER_PK'); +// } + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmountForEth = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); +// const usdcPrice = await oracle.getAssetPrice(usdc.address); + +// const collateralDecimals = (await usdc.decimals()).toString(); +// const principalDecimals = (await dai.decimals()).toString(); + +// const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountUSDCtoSwap.toString()) +// .times( +// new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) +// ) +// .div( +// new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) +// ) +// .toFixed(0) +// ); + +// // Make a deposit for user +// await usdc.connect(user).mint(amountUSDCtoSwap); +// await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); +// await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + +// const aUsdcData = await pool.getReserveData(usdc.address); +// const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); +// await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); + +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); +// const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); + +// const aWethNonce = (await aWETH._nonces(userAddress)).toNumber(); +// const aWethMsgParams = buildPermitParams( +// chainId, +// aWETH.address, +// '1', +// await aWETH.name(), +// userAddress, +// uniswapLiquiditySwapAdapter.address, +// aWethNonce, +// deadline, +// amountWETHtoSwap.toString() +// ); +// const { v: aWETHv, r: aWETHr, s: aWETHs } = getSignatureFromTypedData( +// ownerPrivateKey, +// aWethMsgParams +// ); + +// const aUsdcNonce = (await aUsdc._nonces(userAddress)).toNumber(); +// const aUsdcMsgParams = buildPermitParams( +// chainId, +// aUsdc.address, +// '1', +// await aUsdc.name(), +// userAddress, +// uniswapLiquiditySwapAdapter.address, +// aUsdcNonce, +// deadline, +// amountUSDCtoSwap.toString() +// ); +// const { v: aUsdcv, r: aUsdcr, s: aUsdcs } = getSignatureFromTypedData( +// ownerPrivateKey, +// aUsdcMsgParams +// ); + +// await uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( +// [weth.address, usdc.address], +// [dai.address, dai.address], +// [amountWETHtoSwap, amountUSDCtoSwap], +// [expectedDaiAmountForEth, expectedDaiAmountForUsdc], +// [ +// { +// amount: amountWETHtoSwap, +// deadline, +// v: aWETHv, +// r: aWETHr, +// s: aWETHs, +// }, +// { +// amount: amountUSDCtoSwap, +// deadline, +// v: aUsdcv, +// r: aUsdcr, +// s: aUsdcs, +// }, +// ], +// [false, false] +// ); + +// const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const userAUsdcBalance = await aUsdc.balanceOf(userAddress); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); +// expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); +// expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); +// }); + +// it('should correctly swap all the balance when using a bigger amount', async () => { +// const { users, weth, oracle, dai, aDai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + +// // Remove other balance +// await aWETH.connect(user).transfer(users[1].address, parseEther('90')); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// // User will swap liquidity 10 aEth to aDai +// const liquidityToSwap = parseEther('10'); +// expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); + +// // User will swap liquidity 10 aEth to aDai +// await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); + +// // Only has 10 atokens, so all the balance will be swapped +// const bigAmountToSwap = parseEther('100'); + +// await expect( +// uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( +// [weth.address], +// [dai.address], +// [bigAmountToSwap], +// [expectedDaiAmount], +// [ +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// ], +// [false] +// ) +// ) +// .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') +// .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); + +// const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(userADaiBalance).to.be.eq(expectedDaiAmount); +// expect(userAEthBalance).to.be.eq(Zero); +// expect(adapterAEthBalance).to.be.eq(Zero); +// }); + +// it('should correctly swap all the balance when using permit', async () => { +// const { users, weth, oracle, dai, aDai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); + +// // Remove other balance +// await aWETH.connect(user).transfer(users[1].address, parseEther('90')); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// // User will swap liquidity 10 aEth to aDai +// const liquidityToSwap = parseEther('10'); +// expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); + +// // Only has 10 atokens, so all the balance will be swapped +// const bigAmountToSwap = parseEther('100'); + +// const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; +// const deadline = MAX_UINT_AMOUNT; + +// const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; +// if (!ownerPrivateKey) { +// throw new Error('INVALID_OWNER_PK'); +// } +// const aWethNonce = (await aWETH._nonces(userAddress)).toNumber(); +// const aWethMsgParams = buildPermitParams( +// chainId, +// aWETH.address, +// '1', +// await aWETH.name(), +// userAddress, +// uniswapLiquiditySwapAdapter.address, +// aWethNonce, +// deadline, +// bigAmountToSwap.toString() +// ); +// const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, aWethMsgParams); + +// await expect( +// uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( +// [weth.address], +// [dai.address], +// [bigAmountToSwap], +// [expectedDaiAmount], +// [ +// { +// amount: bigAmountToSwap, +// deadline, +// v, +// r, +// s, +// }, +// ], +// [false] +// ) +// ) +// .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') +// .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); + +// const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); +// const adapterDaiAllowance = await dai.allowance( +// uniswapLiquiditySwapAdapter.address, +// userAddress +// ); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(adapterDaiAllowance).to.be.eq(Zero); +// expect(userADaiBalance).to.be.eq(expectedDaiAmount); +// expect(userAEthBalance).to.be.eq(Zero); +// expect(adapterAEthBalance).to.be.eq(Zero); +// }); +// }); +// }); +// }); diff --git a/test-suites/test-lp/uniswapAdapters.repay.spec.ts b/test-suites/test-lp/uniswapAdapters.repay.spec.ts new file mode 100644 index 00000000..7aace380 --- /dev/null +++ b/test-suites/test-lp/uniswapAdapters.repay.spec.ts @@ -0,0 +1,1469 @@ +// import { makeSuite, TestEnv } from './helpers/make-suite'; +// import { +// convertToCurrencyDecimals, +// getContract, +// buildPermitParams, +// getSignatureFromTypedData, +// buildRepayAdapterParams, +// } from '../../helpers/contracts-helpers'; +// import { getMockUniswapRouter } from '../../helpers/contracts-getters'; +// import { deployUniswapRepayAdapter } from '../../helpers/contracts-deployments'; +// import { MockUniswapV2Router02 } from '../../types/MockUniswapV2Router02'; +// import { Zero } from '@ethersproject/constants'; +// import BigNumber from 'bignumber.js'; +// import { DRE, evmRevert, evmSnapshot } from '../../helpers/misc-utils'; +// import { ethers } from 'ethers'; +// import { eContractid } from '../../helpers/types'; +// import { StableDebtToken } from '../../types/StableDebtToken'; +// import { BUIDLEREVM_CHAINID } from '../../helpers/buidler-constants'; +// import { MAX_UINT_AMOUNT } from '../../helpers/constants'; +// import { VariableDebtToken } from '../../types'; +// const { parseEther } = ethers.utils; + +// const { expect } = require('chai'); + +// makeSuite('Uniswap adapters', (testEnv: TestEnv) => { +// let mockUniswapRouter: MockUniswapV2Router02; +// let evmSnapshotId: string; + +// before(async () => { +// mockUniswapRouter = await getMockUniswapRouter(); +// }); + +// beforeEach(async () => { +// evmSnapshotId = await evmSnapshot(); +// }); + +// afterEach(async () => { +// await evmRevert(evmSnapshotId); +// }); + +// describe('UniswapRepayAdapter', () => { +// beforeEach(async () => { +// const { users, weth, dai, usdc, aave, pool, deployer } = testEnv; +// const userAddress = users[0].address; + +// // Provide liquidity +// await dai.mint(parseEther('20000')); +// await dai.approve(pool.address, parseEther('20000')); +// await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); + +// const usdcLiquidity = await convertToCurrencyDecimals(usdc.address, '2000000'); +// await usdc.mint(usdcLiquidity); +// await usdc.approve(pool.address, usdcLiquidity); +// await pool.deposit(usdc.address, usdcLiquidity, deployer.address, 0); + +// await weth.mint(parseEther('100')); +// await weth.approve(pool.address, parseEther('100')); +// await pool.deposit(weth.address, parseEther('100'), deployer.address, 0); + +// await aave.mint(parseEther('1000000')); +// await aave.approve(pool.address, parseEther('1000000')); +// await pool.deposit(aave.address, parseEther('1000000'), deployer.address, 0); + +// // Make a deposit for user +// await weth.mint(parseEther('1000')); +// await weth.approve(pool.address, parseEther('1000')); +// await pool.deposit(weth.address, parseEther('1000'), userAddress, 0); + +// await aave.mint(parseEther('1000000')); +// await aave.approve(pool.address, parseEther('1000000')); +// await pool.deposit(aave.address, parseEther('1000000'), userAddress, 0); + +// await usdc.mint(usdcLiquidity); +// await usdc.approve(pool.address, usdcLiquidity); +// await pool.deposit(usdc.address, usdcLiquidity, userAddress, 0); +// }); + +// describe('constructor', () => { +// it('should deploy with correct parameters', async () => { +// const { addressesProvider, weth } = testEnv; +// await deployUniswapRepayAdapter([ +// addressesProvider.address, +// mockUniswapRouter.address, +// weth.address, +// ]); +// }); + +// it('should revert if not valid addresses provider', async () => { +// const { weth } = testEnv; +// expect( +// deployUniswapRepayAdapter([ +// mockUniswapRouter.address, +// mockUniswapRouter.address, +// weth.address, +// ]) +// ).to.be.reverted; +// }); +// }); + +// describe('executeOperation', () => { +// it('should correctly swap tokens and repay debt', async () => { +// const { +// users, +// pool, +// weth, +// aWETH, +// oracle, +// dai, +// uniswapRepayAdapter, +// helpersContract, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + +// const daiStableDebtTokenAddress = ( +// await helpersContract.getReserveTokensAddresses(dai.address) +// ).stableDebtTokenAddress; + +// const daiStableDebtContract = await getContract( +// eContractid.StableDebtToken, +// daiStableDebtTokenAddress +// ); + +// const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + +// const liquidityToSwap = amountWETHtoSwap; +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); + +// const flashLoanDebt = new BigNumber(expectedDaiAmount.toString()) +// .multipliedBy(1.0009) +// .toFixed(0); + +// await mockUniswapRouter.setAmountIn( +// flashLoanDebt, +// weth.address, +// dai.address, +// liquidityToSwap +// ); + +// const params = buildRepayAdapterParams( +// weth.address, +// liquidityToSwap, +// 1, +// 0, +// 0, +// 0, +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// false +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapRepayAdapter.address, +// [dai.address], +// [expectedDaiAmount.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ) +// .to.emit(uniswapRepayAdapter, 'Swapped') +// .withArgs(weth.address, dai.address, liquidityToSwap.toString(), flashLoanDebt); + +// const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); +// const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); +// expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); +// }); + +// it('should correctly swap tokens and repay debt with permit', async () => { +// const { +// users, +// pool, +// weth, +// aWETH, +// oracle, +// dai, +// uniswapRepayAdapter, +// helpersContract, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + +// const daiStableDebtTokenAddress = ( +// await helpersContract.getReserveTokensAddresses(dai.address) +// ).stableDebtTokenAddress; + +// const daiStableDebtContract = await getContract( +// eContractid.StableDebtToken, +// daiStableDebtTokenAddress +// ); + +// const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + +// const liquidityToSwap = amountWETHtoSwap; +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; +// const deadline = MAX_UINT_AMOUNT; +// const nonce = (await aWETH._nonces(userAddress)).toNumber(); +// const msgParams = buildPermitParams( +// chainId, +// aWETH.address, +// '1', +// await aWETH.name(), +// userAddress, +// uniswapRepayAdapter.address, +// nonce, +// deadline, +// liquidityToSwap.toString() +// ); + +// const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; +// if (!ownerPrivateKey) { +// throw new Error('INVALID_OWNER_PK'); +// } + +// const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); + +// const flashLoanDebt = new BigNumber(expectedDaiAmount.toString()) +// .multipliedBy(1.0009) +// .toFixed(0); + +// await mockUniswapRouter.setAmountIn( +// flashLoanDebt, +// weth.address, +// dai.address, +// liquidityToSwap +// ); + +// const params = buildRepayAdapterParams( +// weth.address, +// liquidityToSwap, +// 1, +// liquidityToSwap, +// deadline, +// v, +// r, +// s, +// false +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapRepayAdapter.address, +// [dai.address], +// [expectedDaiAmount.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ) +// .to.emit(uniswapRepayAdapter, 'Swapped') +// .withArgs(weth.address, dai.address, liquidityToSwap.toString(), flashLoanDebt); + +// const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); +// const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); +// expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); +// }); + +// it('should revert if caller not lending pool', async () => { +// const { users, pool, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + +// const liquidityToSwap = amountWETHtoSwap; +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); + +// const params = buildRepayAdapterParams( +// weth.address, +// liquidityToSwap, +// 1, +// 0, +// 0, +// 0, +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// false +// ); + +// await expect( +// uniswapRepayAdapter +// .connect(user) +// .executeOperation( +// [dai.address], +// [expectedDaiAmount.toString()], +// [0], +// userAddress, +// params +// ) +// ).to.be.revertedWith('CALLER_MUST_BE_LENDING_POOL'); +// }); + +// it('should revert if there is not debt to repay with the specified rate mode', async () => { +// const { users, pool, weth, oracle, dai, uniswapRepayAdapter, aWETH } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// await weth.connect(user).mint(amountWETHtoSwap); +// await weth.connect(user).transfer(uniswapRepayAdapter.address, amountWETHtoSwap); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress); + +// const liquidityToSwap = amountWETHtoSwap; +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); + +// const params = buildRepayAdapterParams( +// weth.address, +// liquidityToSwap, +// 1, +// 0, +// 0, +// 0, +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// false +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapRepayAdapter.address, +// [dai.address], +// [expectedDaiAmount.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ).to.be.reverted; +// }); + +// it('should revert if there is not debt to repay', async () => { +// const { users, pool, weth, oracle, dai, uniswapRepayAdapter, aWETH } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// await weth.connect(user).mint(amountWETHtoSwap); +// await weth.connect(user).transfer(uniswapRepayAdapter.address, amountWETHtoSwap); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// const liquidityToSwap = amountWETHtoSwap; +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); + +// const params = buildRepayAdapterParams( +// weth.address, +// liquidityToSwap, +// 1, +// 0, +// 0, +// 0, +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// false +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapRepayAdapter.address, +// [dai.address], +// [expectedDaiAmount.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ).to.be.reverted; +// }); + +// it('should revert when max amount allowed to swap is bigger than max slippage', async () => { +// const { users, pool, weth, oracle, dai, aWETH, uniswapRepayAdapter } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + +// const bigMaxAmountToSwap = amountWETHtoSwap.mul(2); +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, bigMaxAmountToSwap); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, bigMaxAmountToSwap); + +// const flashLoanDebt = new BigNumber(expectedDaiAmount.toString()) +// .multipliedBy(1.0009) +// .toFixed(0); + +// await mockUniswapRouter.setAmountIn( +// flashLoanDebt, +// weth.address, +// dai.address, +// bigMaxAmountToSwap +// ); + +// const params = buildRepayAdapterParams( +// weth.address, +// bigMaxAmountToSwap, +// 1, +// 0, +// 0, +// 0, +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// false +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapRepayAdapter.address, +// [dai.address], +// [expectedDaiAmount.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ).to.be.revertedWith('maxAmountToSwap exceed max slippage'); +// }); + +// it('should swap, repay debt and pull the needed ATokens leaving no leftovers', async () => { +// const { +// users, +// pool, +// weth, +// aWETH, +// oracle, +// dai, +// uniswapRepayAdapter, +// helpersContract, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + +// const daiStableDebtTokenAddress = ( +// await helpersContract.getReserveTokensAddresses(dai.address) +// ).stableDebtTokenAddress; + +// const daiStableDebtContract = await getContract( +// eContractid.StableDebtToken, +// daiStableDebtTokenAddress +// ); + +// const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + +// const liquidityToSwap = amountWETHtoSwap; +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); +// const userWethBalanceBefore = await weth.balanceOf(userAddress); + +// const actualWEthSwapped = new BigNumber(liquidityToSwap.toString()) +// .multipliedBy(0.995) +// .toFixed(0); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped); + +// const flashLoanDebt = new BigNumber(expectedDaiAmount.toString()) +// .multipliedBy(1.0009) +// .toFixed(0); + +// await mockUniswapRouter.setAmountIn( +// flashLoanDebt, +// weth.address, +// dai.address, +// actualWEthSwapped +// ); + +// const params = buildRepayAdapterParams( +// weth.address, +// liquidityToSwap, +// 1, +// 0, +// 0, +// 0, +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// false +// ); + +// await expect( +// pool +// .connect(user) +// .flashLoan( +// uniswapRepayAdapter.address, +// [dai.address], +// [expectedDaiAmount.toString()], +// [0], +// userAddress, +// params, +// 0 +// ) +// ) +// .to.emit(uniswapRepayAdapter, 'Swapped') +// .withArgs(weth.address, dai.address, actualWEthSwapped.toString(), flashLoanDebt); + +// const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); +// const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); +// const userWethBalance = await weth.balanceOf(userAddress); + +// expect(adapterAEthBalance).to.be.eq(Zero); +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); +// expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(actualWEthSwapped)); +// expect(userWethBalance).to.be.eq(userWethBalanceBefore); +// }); + +// it('should correctly swap tokens and repay the whole stable debt', async () => { +// const { +// users, +// pool, +// weth, +// aWETH, +// oracle, +// dai, +// uniswapRepayAdapter, +// helpersContract, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + +// const daiStableDebtTokenAddress = ( +// await helpersContract.getReserveTokensAddresses(dai.address) +// ).stableDebtTokenAddress; + +// const daiStableDebtContract = await getContract( +// eContractid.StableDebtToken, +// daiStableDebtTokenAddress +// ); + +// const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + +// // Add a % to repay on top of the debt +// const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString()) +// .multipliedBy(1.1) +// .toFixed(0); + +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// // Add a % to repay on top of the debt +// const amountToRepay = new BigNumber(expectedDaiAmount.toString()) +// .multipliedBy(1.1) +// .toFixed(0); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap); +// await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap); + +// const params = buildRepayAdapterParams( +// weth.address, +// liquidityToSwap, +// 1, +// 0, +// 0, +// 0, +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// false +// ); + +// await pool +// .connect(user) +// .flashLoan( +// uniswapRepayAdapter.address, +// [dai.address], +// [amountToRepay.toString()], +// [0], +// userAddress, +// params, +// 0 +// ); + +// const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); +// const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); + +// expect(adapterAEthBalance).to.be.eq(Zero); +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); +// expect(userDaiStableDebtAmount).to.be.eq(Zero); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); +// }); + +// it('should correctly swap tokens and repay the whole variable debt', async () => { +// const { +// users, +// pool, +// weth, +// aWETH, +// oracle, +// dai, +// uniswapRepayAdapter, +// helpersContract, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress); + +// const daiStableVariableTokenAddress = ( +// await helpersContract.getReserveTokensAddresses(dai.address) +// ).variableDebtTokenAddress; + +// const daiVariableDebtContract = await getContract( +// eContractid.VariableDebtToken, +// daiStableVariableTokenAddress +// ); + +// const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( +// userAddress +// ); + +// // Add a % to repay on top of the debt +// const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString()) +// .multipliedBy(1.1) +// .toFixed(0); + +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// // Add a % to repay on top of the debt +// const amountToRepay = new BigNumber(expectedDaiAmount.toString()) +// .multipliedBy(1.1) +// .toFixed(0); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap); +// await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap); + +// const params = buildRepayAdapterParams( +// weth.address, +// liquidityToSwap, +// 2, +// 0, +// 0, +// 0, +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// false +// ); + +// await pool +// .connect(user) +// .flashLoan( +// uniswapRepayAdapter.address, +// [dai.address], +// [amountToRepay.toString()], +// [0], +// userAddress, +// params, +// 0 +// ); + +// const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); +// const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); + +// expect(adapterAEthBalance).to.be.eq(Zero); +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(userDaiVariableDebtAmountBefore).to.be.gte(expectedDaiAmount); +// expect(userDaiVariableDebtAmount).to.be.eq(Zero); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); +// }); + +// it('should correctly repay debt via flash loan using the same asset as collateral', async () => { +// const { users, pool, aDai, dai, uniswapRepayAdapter, helpersContract } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// // Add deposit for user +// await dai.mint(parseEther('30')); +// await dai.approve(pool.address, parseEther('30')); +// await pool.deposit(dai.address, parseEther('30'), userAddress, 0); + +// const amountCollateralToSwap = parseEther('10'); +// const debtAmount = parseEther('10'); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, debtAmount, 2, 0, userAddress); + +// const daiVariableDebtTokenAddress = ( +// await helpersContract.getReserveTokensAddresses(dai.address) +// ).variableDebtTokenAddress; + +// const daiVariableDebtContract = await getContract( +// eContractid.VariableDebtToken, +// daiVariableDebtTokenAddress +// ); + +// const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( +// userAddress +// ); + +// const flashLoanDebt = new BigNumber(amountCollateralToSwap.toString()) +// .multipliedBy(1.0009) +// .toFixed(0); + +// await aDai.connect(user).approve(uniswapRepayAdapter.address, flashLoanDebt); +// const userADaiBalanceBefore = await aDai.balanceOf(userAddress); +// const userDaiBalanceBefore = await dai.balanceOf(userAddress); + +// const params = buildRepayAdapterParams( +// dai.address, +// amountCollateralToSwap, +// 2, +// 0, +// 0, +// 0, +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// '0x0000000000000000000000000000000000000000000000000000000000000000', +// false +// ); + +// await pool +// .connect(user) +// .flashLoan( +// uniswapRepayAdapter.address, +// [dai.address], +// [amountCollateralToSwap.toString()], +// [0], +// userAddress, +// params, +// 0 +// ); + +// const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); +// const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const adapterADaiBalance = await aDai.balanceOf(uniswapRepayAdapter.address); +// const userDaiBalance = await dai.balanceOf(userAddress); + +// expect(adapterADaiBalance).to.be.eq(Zero, 'adapter aDAI balance should be zero'); +// expect(adapterDaiBalance).to.be.eq(Zero, 'adapter DAI balance should be zero'); +// expect(userDaiVariableDebtAmountBefore).to.be.gte( +// debtAmount, +// ' user DAI variable debt before should be gte debtAmount' +// ); +// expect(userDaiVariableDebtAmount).to.be.lt( +// debtAmount, +// 'user dai variable debt amount should be lt debt amount' +// ); +// expect(userADaiBalance).to.be.lt( +// userADaiBalanceBefore, +// 'user aDAI balance should be lt aDAI prior balance' +// ); +// expect(userADaiBalance).to.be.gte( +// userADaiBalanceBefore.sub(flashLoanDebt), +// 'user aDAI balance should be gte aDAI prior balance sub flash loan debt' +// ); +// expect(userDaiBalance).to.be.eq(userDaiBalanceBefore, 'user dai balance eq prior balance'); +// }); +// }); + +// describe('swapAndRepay', () => { +// it('should correctly swap tokens and repay debt', async () => { +// const { +// users, +// pool, +// weth, +// aWETH, +// oracle, +// dai, +// uniswapRepayAdapter, +// helpersContract, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + +// const daiStableDebtTokenAddress = ( +// await helpersContract.getReserveTokensAddresses(dai.address) +// ).stableDebtTokenAddress; + +// const daiStableDebtContract = await getContract( +// eContractid.StableDebtToken, +// daiStableDebtTokenAddress +// ); + +// const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + +// const liquidityToSwap = amountWETHtoSwap; +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap); + +// await mockUniswapRouter.setDefaultMockValue(liquidityToSwap); + +// await uniswapRepayAdapter.connect(user).swapAndRepay( +// weth.address, +// dai.address, +// liquidityToSwap, +// expectedDaiAmount, +// 1, +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// false +// ); + +// const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); +// const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); +// expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); +// }); + +// it('should correctly swap tokens and repay debt with permit', async () => { +// const { +// users, +// pool, +// weth, +// aWETH, +// oracle, +// dai, +// uniswapRepayAdapter, +// helpersContract, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + +// const daiStableDebtTokenAddress = ( +// await helpersContract.getReserveTokensAddresses(dai.address) +// ).stableDebtTokenAddress; + +// const daiStableDebtContract = await getContract( +// eContractid.StableDebtToken, +// daiStableDebtTokenAddress +// ); + +// const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + +// const liquidityToSwap = amountWETHtoSwap; +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap); + +// await mockUniswapRouter.setDefaultMockValue(liquidityToSwap); + +// const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; +// const deadline = MAX_UINT_AMOUNT; +// const nonce = (await aWETH._nonces(userAddress)).toNumber(); +// const msgParams = buildPermitParams( +// chainId, +// aWETH.address, +// '1', +// await aWETH.name(), +// userAddress, +// uniswapRepayAdapter.address, +// nonce, +// deadline, +// liquidityToSwap.toString() +// ); + +// const ownerPrivateKey = require('../../test-wallets.js').accounts[1].secretKey; +// if (!ownerPrivateKey) { +// throw new Error('INVALID_OWNER_PK'); +// } + +// const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); + +// await uniswapRepayAdapter.connect(user).swapAndRepay( +// weth.address, +// dai.address, +// liquidityToSwap, +// expectedDaiAmount, +// 1, +// { +// amount: liquidityToSwap, +// deadline, +// v, +// r, +// s, +// }, +// false +// ); + +// const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); +// const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); + +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); +// expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); +// }); + +// it('should revert if there is not debt to repay', async () => { +// const { users, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv; +// const user = users[0].signer; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// const liquidityToSwap = amountWETHtoSwap; +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); + +// await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap); + +// await mockUniswapRouter.setDefaultMockValue(liquidityToSwap); + +// await expect( +// uniswapRepayAdapter.connect(user).swapAndRepay( +// weth.address, +// dai.address, +// liquidityToSwap, +// expectedDaiAmount, +// 1, +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// false +// ) +// ).to.be.reverted; +// }); + +// it('should revert when max amount allowed to swap is bigger than max slippage', async () => { +// const { users, pool, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + +// const bigMaxAmountToSwap = amountWETHtoSwap.mul(2); +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, bigMaxAmountToSwap); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, bigMaxAmountToSwap); + +// await mockUniswapRouter.setDefaultMockValue(bigMaxAmountToSwap); + +// await expect( +// uniswapRepayAdapter.connect(user).swapAndRepay( +// weth.address, +// dai.address, +// bigMaxAmountToSwap, +// expectedDaiAmount, +// 1, +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// false +// ) +// ).to.be.revertedWith('maxAmountToSwap exceed max slippage'); +// }); + +// it('should swap, repay debt and pull the needed ATokens leaving no leftovers', async () => { +// const { +// users, +// pool, +// weth, +// aWETH, +// oracle, +// dai, +// uniswapRepayAdapter, +// helpersContract, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + +// const daiStableDebtTokenAddress = ( +// await helpersContract.getReserveTokensAddresses(dai.address) +// ).stableDebtTokenAddress; + +// const daiStableDebtContract = await getContract( +// eContractid.StableDebtToken, +// daiStableDebtTokenAddress +// ); + +// const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + +// const liquidityToSwap = amountWETHtoSwap; +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); +// const userWethBalanceBefore = await weth.balanceOf(userAddress); + +// const actualWEthSwapped = new BigNumber(liquidityToSwap.toString()) +// .multipliedBy(0.995) +// .toFixed(0); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped); + +// await mockUniswapRouter.setDefaultMockValue(actualWEthSwapped); + +// await uniswapRepayAdapter.connect(user).swapAndRepay( +// weth.address, +// dai.address, +// liquidityToSwap, +// expectedDaiAmount, +// 1, +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// false +// ); + +// const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); +// const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); +// const userWethBalance = await weth.balanceOf(userAddress); + +// expect(adapterAEthBalance).to.be.eq(Zero); +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); +// expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(actualWEthSwapped)); +// expect(userWethBalance).to.be.eq(userWethBalanceBefore); +// }); + +// it('should correctly swap tokens and repay the whole stable debt', async () => { +// const { +// users, +// pool, +// weth, +// aWETH, +// oracle, +// dai, +// uniswapRepayAdapter, +// helpersContract, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); + +// const daiStableDebtTokenAddress = ( +// await helpersContract.getReserveTokensAddresses(dai.address) +// ).stableDebtTokenAddress; + +// const daiStableDebtContract = await getContract( +// eContractid.StableDebtToken, +// daiStableDebtTokenAddress +// ); + +// const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + +// // Add a % to repay on top of the debt +// const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString()) +// .multipliedBy(1.1) +// .toFixed(0); + +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// // Add a % to repay on top of the debt +// const amountToRepay = new BigNumber(expectedDaiAmount.toString()) +// .multipliedBy(1.1) +// .toFixed(0); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap); +// await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap); + +// await uniswapRepayAdapter.connect(user).swapAndRepay( +// weth.address, +// dai.address, +// liquidityToSwap, +// amountToRepay, +// 1, +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// false +// ); + +// const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); +// const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); + +// expect(adapterAEthBalance).to.be.eq(Zero); +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); +// expect(userDaiStableDebtAmount).to.be.eq(Zero); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); +// }); + +// it('should correctly swap tokens and repay the whole variable debt', async () => { +// const { +// users, +// pool, +// weth, +// aWETH, +// oracle, +// dai, +// uniswapRepayAdapter, +// helpersContract, +// } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + +// const daiPrice = await oracle.getAssetPrice(dai.address); +// const expectedDaiAmount = await convertToCurrencyDecimals( +// dai.address, +// new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) +// ); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress); + +// const daiStableVariableTokenAddress = ( +// await helpersContract.getReserveTokensAddresses(dai.address) +// ).variableDebtTokenAddress; + +// const daiVariableDebtContract = await getContract( +// eContractid.VariableDebtToken, +// daiStableVariableTokenAddress +// ); + +// const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( +// userAddress +// ); + +// // Add a % to repay on top of the debt +// const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString()) +// .multipliedBy(1.1) +// .toFixed(0); + +// await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); +// const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + +// // Add a % to repay on top of the debt +// const amountToRepay = new BigNumber(expectedDaiAmount.toString()) +// .multipliedBy(1.1) +// .toFixed(0); + +// await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap); +// await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap); + +// await uniswapRepayAdapter.connect(user).swapAndRepay( +// weth.address, +// dai.address, +// liquidityToSwap, +// amountToRepay, +// 2, +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// false +// ); + +// const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); +// const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); +// const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); +// const userAEthBalance = await aWETH.balanceOf(userAddress); +// const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); + +// expect(adapterAEthBalance).to.be.eq(Zero); +// expect(adapterWethBalance).to.be.eq(Zero); +// expect(adapterDaiBalance).to.be.eq(Zero); +// expect(userDaiVariableDebtAmountBefore).to.be.gte(expectedDaiAmount); +// expect(userDaiVariableDebtAmount).to.be.eq(Zero); +// expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); +// expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); +// }); + +// it('should correctly repay debt using the same asset as collateral', async () => { +// const { users, pool, dai, uniswapRepayAdapter, helpersContract, aDai } = testEnv; +// const user = users[0].signer; +// const userAddress = users[0].address; + +// // Add deposit for user +// await dai.mint(parseEther('30')); +// await dai.approve(pool.address, parseEther('30')); +// await pool.deposit(dai.address, parseEther('30'), userAddress, 0); + +// const amountCollateralToSwap = parseEther('4'); + +// const debtAmount = parseEther('3'); + +// // Open user Debt +// await pool.connect(user).borrow(dai.address, debtAmount, 2, 0, userAddress); + +// const daiVariableDebtTokenAddress = ( +// await helpersContract.getReserveTokensAddresses(dai.address) +// ).variableDebtTokenAddress; + +// const daiVariableDebtContract = await getContract( +// eContractid.StableDebtToken, +// daiVariableDebtTokenAddress +// ); + +// const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( +// userAddress +// ); + +// await aDai.connect(user).approve(uniswapRepayAdapter.address, amountCollateralToSwap); +// const userADaiBalanceBefore = await aDai.balanceOf(userAddress); +// const userDaiBalanceBefore = await dai.balanceOf(userAddress); + +// await uniswapRepayAdapter.connect(user).swapAndRepay( +// dai.address, +// dai.address, +// amountCollateralToSwap, +// amountCollateralToSwap, +// 2, +// { +// amount: 0, +// deadline: 0, +// v: 0, +// r: '0x0000000000000000000000000000000000000000000000000000000000000000', +// s: '0x0000000000000000000000000000000000000000000000000000000000000000', +// }, +// false +// ); + +// const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); +// const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); +// const userADaiBalance = await aDai.balanceOf(userAddress); +// const adapterADaiBalance = await aDai.balanceOf(uniswapRepayAdapter.address); +// const userDaiBalance = await dai.balanceOf(userAddress); + +// expect(adapterADaiBalance).to.be.eq(Zero, 'adapter aADAI should be zero'); +// expect(adapterDaiBalance).to.be.eq(Zero, 'adapter DAI should be zero'); +// expect(userDaiVariableDebtAmountBefore).to.be.gte( +// debtAmount, +// 'user dai variable debt before should be gte debtAmount' +// ); +// expect(userDaiVariableDebtAmount).to.be.lt( +// debtAmount, +// 'current user dai variable debt amount should be less than debtAmount' +// ); +// expect(userADaiBalance).to.be.lt( +// userADaiBalanceBefore, +// 'current user aDAI balance should be less than prior balance' +// ); +// expect(userADaiBalance).to.be.gte( +// userADaiBalanceBefore.sub(amountCollateralToSwap), +// 'current user aDAI balance should be gte user balance sub swapped collateral' +// ); +// expect(userDaiBalance).to.be.eq( +// userDaiBalanceBefore, +// 'user DAI balance should remain equal' +// ); +// }); +// }); +// }); +// }); diff --git a/test-suites/test-lp/upgradeability.spec.ts b/test-suites/test-lp/upgradeability.spec.ts new file mode 100644 index 00000000..771ae6ed --- /dev/null +++ b/test-suites/test-lp/upgradeability.spec.ts @@ -0,0 +1,234 @@ +import { expect } from 'chai'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors, eContractid } from '../../helpers/types'; +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, + getMockStableDebtToken, + getMockVariableDebtToken, + getStableDebtToken, + getVariableDebtToken, +} from '../../helpers/contracts-getters'; +import { + deployMockAToken, + deployMockStableDebtToken, + deployMockVariableDebtToken, +} from '../../helpers/contracts-deployments'; + +makeSuite('Upgradeability', (testEnv: TestEnv) => { + const { CALLER_NOT_POOL_ADMIN } = ProtocolErrors; + let newATokenAddress: string; + let newStableTokenAddress: string; + let newVariableTokenAddress: string; + + before('deploying instances', async () => { + const { dai, pool } = testEnv; + const aTokenInstance = await deployMockAToken([ + pool.address, + dai.address, + ZERO_ADDRESS, + ZERO_ADDRESS, + 'Aave Interest bearing UniDAI updated', + 'aUniDAI', + ]); + + const stableDebtTokenInstance = await deployMockStableDebtToken([ + pool.address, + dai.address, + ZERO_ADDRESS, + 'Aave stable debt bearing UniDAI updated', + 'stableDebtUniDAI', + ]); + + const variableDebtTokenInstance = await deployMockVariableDebtToken([ + pool.address, + dai.address, + ZERO_ADDRESS, + 'Aave variable debt bearing UniDAI updated', + 'variableDebtUniDAI', + ]); + + newATokenAddress = aTokenInstance.address; + newVariableTokenAddress = variableDebtTokenInstance.address; + newStableTokenAddress = stableDebtTokenInstance.address; + }); + + it('Tries to update the DAI Atoken implementation with a different address than the lendingPoolManager', async () => { + const { dai, configurator, users } = testEnv; + + const name = await (await getAToken(newATokenAddress)).name(); + const symbol = await (await getAToken(newATokenAddress)).symbol(); + + const updateATokenInputParams: { + asset: string; + treasury: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + treasury: ZERO_ADDRESS, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newATokenAddress, + }; + await expect( + configurator.connect(users[1].signer).updateAToken(updateATokenInputParams) + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Upgrades the DAI Atoken implementation ', async () => { + const { dai, configurator, aDai } = testEnv; + + const name = await (await getAToken(newATokenAddress)).name(); + const symbol = await (await getAToken(newATokenAddress)).symbol(); + + const updateATokenInputParams: { + asset: string; + treasury: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + treasury: ZERO_ADDRESS, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newATokenAddress, + }; + await configurator.updateAToken(updateATokenInputParams); + + const tokenName = await aDai.name(); + + expect(tokenName).to.be.eq('Aave Interest bearing UniDAI updated', 'Invalid token name'); + }); + + it('Tries to update the DAI Stable debt token implementation with a different address than the lendingPoolManager', async () => { + const { dai, configurator, users } = testEnv; + + const name = await (await getStableDebtToken(newStableTokenAddress)).name(); + const symbol = await (await getStableDebtToken(newStableTokenAddress)).symbol(); + + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newStableTokenAddress, + } + + await expect( + configurator + .connect(users[1].signer) + .updateStableDebtToken(updateDebtTokenInput) + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Upgrades the DAI stable debt token implementation ', async () => { + const { dai, configurator, pool, helpersContract } = testEnv; + + const name = await (await getStableDebtToken(newStableTokenAddress)).name(); + const symbol = await (await getStableDebtToken(newStableTokenAddress)).symbol(); + + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newStableTokenAddress, + } + + await configurator.updateStableDebtToken(updateDebtTokenInput); + + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses(dai.address); + + const debtToken = await getMockStableDebtToken(stableDebtTokenAddress); + + const tokenName = await debtToken.name(); + + expect(tokenName).to.be.eq('Aave stable debt bearing UniDAI updated', 'Invalid token name'); + }); + + it('Tries to update the DAI variable debt token implementation with a different address than the lendingPoolManager', async () => { + const {dai, configurator, users} = testEnv; + + const name = await (await getVariableDebtToken(newVariableTokenAddress)).name(); + const symbol = await (await getVariableDebtToken(newVariableTokenAddress)).symbol(); + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newVariableTokenAddress, + } + + await expect( + configurator + .connect(users[1].signer) + .updateVariableDebtToken(updateDebtTokenInput) + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Upgrades the DAI variable debt token implementation ', async () => { + const {dai, configurator, pool, helpersContract} = testEnv; + + const name = await (await getVariableDebtToken(newVariableTokenAddress)).name(); + const symbol = await (await getVariableDebtToken(newVariableTokenAddress)).symbol(); + + const updateDebtTokenInput: { + asset: string; + incentivesController: string; + name: string; + symbol: string; + implementation: string; + } = { + asset: dai.address, + incentivesController: ZERO_ADDRESS, + name: name, + symbol: symbol, + implementation: newVariableTokenAddress, + } + //const name = await (await getAToken(newATokenAddress)).name(); + + await configurator.updateVariableDebtToken(updateDebtTokenInput); + + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + dai.address + ); + + const debtToken = await getMockVariableDebtToken(variableDebtTokenAddress); + + const tokenName = await debtToken.name(); + + expect(tokenName).to.be.eq('Aave variable debt bearing UniDAI updated', 'Invalid token name'); + }); +}); diff --git a/test-suites/test-lp/variable-debt-token.spec.ts b/test-suites/test-lp/variable-debt-token.spec.ts new file mode 100644 index 00000000..d4afbbf0 --- /dev/null +++ b/test-suites/test-lp/variable-debt-token.spec.ts @@ -0,0 +1,36 @@ +import { expect } from 'chai'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors, TokenContractId, eContractid } from '../../helpers/types'; +import { getVariableDebtToken } from '../../helpers/contracts-getters'; + +makeSuite('Variable debt token tests', (testEnv: TestEnv) => { + const { CT_CALLER_MUST_BE_LENDING_POOL } = ProtocolErrors; + + it('Tries to invoke mint not being the LendingPool', async () => { + const { deployer, pool, dai, helpersContract } = testEnv; + + const daiVariableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).variableDebtTokenAddress; + + const variableDebtContract = await getVariableDebtToken(daiVariableDebtTokenAddress); + + await expect( + variableDebtContract.mint(deployer.address, deployer.address, '1', '1') + ).to.be.revertedWith(CT_CALLER_MUST_BE_LENDING_POOL); + }); + + it('Tries to invoke burn not being the LendingPool', async () => { + const { deployer, pool, dai, helpersContract } = testEnv; + + const daiVariableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).variableDebtTokenAddress; + + const variableDebtContract = await getVariableDebtToken(daiVariableDebtTokenAddress); + + await expect(variableDebtContract.burn(deployer.address, '1', '1')).to.be.revertedWith( + CT_CALLER_MUST_BE_LENDING_POOL + ); + }); +}); diff --git a/test-suites/test-lp/weth-gateway.spec.ts b/test-suites/test-lp/weth-gateway.spec.ts new file mode 100644 index 00000000..22939f5c --- /dev/null +++ b/test-suites/test-lp/weth-gateway.spec.ts @@ -0,0 +1,370 @@ +import { MAX_UINT_AMOUNT } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { parseEther } from 'ethers/lib/utils'; +import { DRE, waitForTx } from '../../helpers/misc-utils'; +import { BigNumber } from 'ethers'; +import { getStableDebtToken, getVariableDebtToken } from '../../helpers/contracts-getters'; +import { deploySelfdestructTransferMock } from '../../helpers/contracts-deployments'; + +const { expect } = require('chai'); + +makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => { + const zero = BigNumber.from('0'); + const depositSize = parseEther('5'); + const daiSize = parseEther('10000'); + it('Deposit WETH via WethGateway and DAI', async () => { + const { users, wethGateway, aWETH } = testEnv; + + const user = users[1]; + const depositor = users[0]; + + // Deposit liquidity with native ETH + await wethGateway + .connect(depositor.signer) + .depositETH(depositor.address, '0', { value: depositSize }); + + // Deposit with native ETH + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(depositSize); + }); + + it('Withdraw WETH - Partial', async () => { + const { users, wethGateway, aWETH, pool } = testEnv; + + const user = users[1]; + const priorEthersBalance = await user.signer.getBalance(); + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.'); + + // Partially withdraw native ETH + const partialWithdraw = await convertToCurrencyDecimals(aWETH.address, '2'); + + // Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether + const approveTx = await aWETH + .connect(user.signer) + .approve(wethGateway.address, MAX_UINT_AMOUNT); + const { gasUsed: approveGas } = await waitForTx(approveTx); + + // Partial Withdraw and send native Ether to user + const { gasUsed: withdrawGas } = await waitForTx( + await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) + ); + + const afterPartialEtherBalance = await user.signer.getBalance(); + const afterPartialATokensBalance = await aWETH.balanceOf(user.address); + const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice); + + expect(afterPartialEtherBalance).to.be.equal( + priorEthersBalance.add(partialWithdraw).sub(gasCosts), + 'User ETHER balance should contain the partial withdraw' + ); + expect(afterPartialATokensBalance).to.be.equal( + aTokensBalance.sub(partialWithdraw), + 'User aWETH balance should be substracted' + ); + }); + + it('Withdraw WETH - Full', async () => { + const { users, aWETH, wethGateway, pool } = testEnv; + + const user = users[1]; + const priorEthersBalance = await user.signer.getBalance(); + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.'); + + // Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether + const approveTx = await aWETH + .connect(user.signer) + .approve(wethGateway.address, MAX_UINT_AMOUNT); + const { gasUsed: approveGas } = await waitForTx(approveTx); + + // Full withdraw + const { gasUsed: withdrawGas } = await waitForTx( + await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) + ); + + const afterFullEtherBalance = await user.signer.getBalance(); + const afterFullATokensBalance = await aWETH.balanceOf(user.address); + const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice); + + expect(afterFullEtherBalance).to.be.eq( + priorEthersBalance.add(aTokensBalance).sub(gasCosts), + 'User ETHER balance should contain the full withdraw' + ); + expect(afterFullATokensBalance).to.be.eq(0, 'User aWETH balance should be zero'); + }); + + it('Borrow stable WETH and Full Repay with ETH', async () => { + const { users, wethGateway, aDai, weth, dai, pool, helpersContract } = testEnv; + const borrowSize = parseEther('1'); + const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); + const user = users[1]; + const depositor = users[0]; + + // Deposit with native ETH + await wethGateway + .connect(depositor.signer) + .depositETH(depositor.address, '0', { value: depositSize }); + + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const stableDebtToken = await getStableDebtToken(stableDebtTokenAddress); + + // Deposit 10000 DAI + await dai.connect(user.signer).mint(daiSize); + await dai.connect(user.signer).approve(pool.address, daiSize); + await pool.connect(user.signer).deposit(dai.address, daiSize, user.address, '0'); + + const aTokensBalance = await aDai.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(daiSize); + + // Borrow WETH with WETH as collateral + await waitForTx( + await pool.connect(user.signer).borrow(weth.address, borrowSize, '1', '0', user.address) + ); + + const debtBalance = await stableDebtToken.balanceOf(user.address); + + expect(debtBalance).to.be.gt(zero); + + // Full Repay WETH with native ETH + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) + ); + + const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); + expect(debtBalanceAfterRepay).to.be.eq(zero); + + // Withdraw DAI + await aDai.connect(user.signer).approve(pool.address, MAX_UINT_AMOUNT); + await pool.connect(user.signer).withdraw(dai.address, MAX_UINT_AMOUNT, user.address); + }); + + it('Borrow variable WETH and Full Repay with ETH', async () => { + const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; + const borrowSize = parseEther('1'); + const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); + const user = users[1]; + + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + // Deposit with native ETH + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(depositSize); + + // Borrow WETH with WETH as collateral + await waitForTx( + await pool.connect(user.signer).borrow(weth.address, borrowSize, '2', '0', user.address) + ); + + const debtBalance = await varDebtToken.balanceOf(user.address); + + expect(debtBalance).to.be.gt(zero); + + // Partial Repay WETH loan with native ETH + const partialPayment = repaySize.div(2); + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(partialPayment, '2', user.address, { value: partialPayment }) + ); + + const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); + expect(debtBalanceAfterPartialRepay).to.be.lt(debtBalance); + + // Full Repay WETH loan with native ETH + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) + ); + const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); + expect(debtBalanceAfterFullRepay).to.be.eq(zero); + }); + + it('Borrow ETH via delegateApprove ETH and repays back', async () => { + const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; + const borrowSize = parseEther('1'); + const user = users[2]; + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + const priorDebtBalance = await varDebtToken.balanceOf(user.address); + expect(priorDebtBalance).to.be.eq(zero); + + // Deposit WETH with native ETH + await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + + const aTokensBalance = await aWETH.balanceOf(user.address); + + expect(aTokensBalance).to.be.gt(zero); + expect(aTokensBalance).to.be.gte(depositSize); + + // Delegates borrowing power of WETH to WETHGateway + await waitForTx( + await varDebtToken.connect(user.signer).approveDelegation(wethGateway.address, borrowSize) + ); + + // Borrows ETH with WETH as collateral + await waitForTx(await wethGateway.connect(user.signer).borrowETH(borrowSize, '2', '0')); + + const debtBalance = await varDebtToken.balanceOf(user.address); + + expect(debtBalance).to.be.gt(zero); + + // Full Repay WETH loan with native ETH + await waitForTx( + await wethGateway + .connect(user.signer) + .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) + ); + const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); + expect(debtBalanceAfterFullRepay).to.be.eq(zero); + }); + + it('Should revert if receiver function receives Ether if not WETH', async () => { + const { users, wethGateway } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + + // Call receiver function (empty data + value) + await expect( + user.signer.sendTransaction({ + to: wethGateway.address, + value: amount, + gasLimit: DRE.network.config.gas, + }) + ).to.be.revertedWith('Receive not allowed'); + }); + + it('Should revert if fallback functions is called with Ether', async () => { + const { users, wethGateway } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + const fakeABI = ['function wantToCallFallback()']; + const abiCoder = new DRE.ethers.utils.Interface(fakeABI); + const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []); + + // Call fallback function with value + await expect( + user.signer.sendTransaction({ + to: wethGateway.address, + data: fakeMethodEncoded, + value: amount, + gasLimit: DRE.network.config.gas, + }) + ).to.be.revertedWith('Fallback not allowed'); + }); + + it('Should revert if fallback functions is called', async () => { + const { users, wethGateway } = testEnv; + const user = users[0]; + + const fakeABI = ['function wantToCallFallback()']; + const abiCoder = new DRE.ethers.utils.Interface(fakeABI); + const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []); + + // Call fallback function without value + await expect( + user.signer.sendTransaction({ + to: wethGateway.address, + data: fakeMethodEncoded, + gasLimit: DRE.network.config.gas, + }) + ).to.be.revertedWith('Fallback not allowed'); + }); + + it('Getters should retrieve correct state', async () => { + const { aWETH, weth, pool, wethGateway } = testEnv; + + const WETHAddress = await wethGateway.getWETHAddress(); + const aWETHAddress = await wethGateway.getAWETHAddress(); + const poolAddress = await wethGateway.getLendingPoolAddress(); + + expect(WETHAddress).to.be.equal(weth.address); + expect(aWETHAddress).to.be.equal(aWETH.address); + expect(poolAddress).to.be.equal(pool.address); + }); + + it('Owner can do emergency token recovery', async () => { + const { users, dai, wethGateway, deployer } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + + await dai.connect(user.signer).mint(amount); + const daiBalanceAfterMint = await dai.balanceOf(user.address); + + await dai.connect(user.signer).transfer(wethGateway.address, amount); + const daiBalanceAfterBadTransfer = await dai.balanceOf(user.address); + expect(daiBalanceAfterBadTransfer).to.be.eq( + daiBalanceAfterMint.sub(amount), + 'User should have lost the funds here.' + ); + + await wethGateway + .connect(deployer.signer) + .emergencyTokenTransfer(dai.address, user.address, amount); + const daiBalanceAfterRecovery = await dai.balanceOf(user.address); + + expect(daiBalanceAfterRecovery).to.be.eq( + daiBalanceAfterMint, + 'User should recover the funds due emergency token transfer' + ); + }); + + it('Owner can do emergency native ETH recovery', async () => { + const { users, wethGateway, deployer } = testEnv; + const user = users[0]; + const amount = parseEther('1'); + const userBalancePriorCall = await user.signer.getBalance(); + + // Deploy contract with payable selfdestruct contract + const selfdestructContract = await deploySelfdestructTransferMock(); + + // Selfdestruct the mock, pointing to WETHGateway address + const callTx = await selfdestructContract + .connect(user.signer) + .destroyAndTransfer(wethGateway.address, { value: amount }); + const { gasUsed } = await waitForTx(callTx); + const gasFees = gasUsed.mul(callTx.gasPrice); + const userBalanceAfterCall = await user.signer.getBalance(); + + expect(userBalanceAfterCall).to.be.eq(userBalancePriorCall.sub(amount).sub(gasFees), ''); + ('User should have lost the funds'); + + // Recover the funds from the contract and sends back to the user + await wethGateway.connect(deployer.signer).emergencyEtherTransfer(user.address, amount); + + const userBalanceAfterRecovery = await user.signer.getBalance(); + const wethGatewayAfterRecovery = await DRE.ethers.provider.getBalance(wethGateway.address); + + expect(userBalanceAfterRecovery).to.be.eq( + userBalancePriorCall.sub(gasFees), + 'User should recover the funds due emergency eth transfer.' + ); + expect(wethGatewayAfterRecovery).to.be.eq('0', 'WETHGateway ether balance should be zero.'); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index 5d3b034e..9974c3b6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "noImplicitAny": false, "resolveJsonModule": true }, - "include": ["./scripts", "./test", "./tasks"], + "include": ["./scripts", "./test", "./tasks", "test-suites/test-aave/uniswapAdapters.repay.spec.ts", "test-suites/test-aave/upgradeability.spec.ts", "test-suites/test-aave/variable-debt-token.spec.ts", "test-suites/test-aave/weth-gateway.spec.ts"], "files": [ "./hardhat.config.ts", "./modules/tenderly/tenderly.d.ts", From 10cc590d8c349f8a4175b09f269653ebd9226931 Mon Sep 17 00:00:00 2001 From: Jeff Wentworth Date: Mon, 8 Feb 2021 02:17:55 +0900 Subject: [PATCH 079/219] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1f8d3043..b9039980 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "hardhat": "hardhat", "hardhat:kovan": "hardhat --network kovan", "hardhat:tenderly-main": "hardhat --network tenderlyMain", - "hardhat:ropsten": "hardhat--network ropsten", + "hardhat:ropsten": "hardhat --network ropsten", "hardhat:main": "hardhat --network main", "hardhat:docker": "hardhat --network hardhatevm_docker", "compile": "SKIP_LOAD=true hardhat compile", From e5274928cc065d71b20bc4ff0a460cf006f19c73 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 8 Feb 2021 10:38:14 -0500 Subject: [PATCH 080/219] Fix LP market asset mismatch --- test-suites/test-lp/helpers/make-suite.ts | 2 +- test-suites/test-lp/helpers/utils/calculations.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/test-suites/test-lp/helpers/make-suite.ts b/test-suites/test-lp/helpers/make-suite.ts index 2c005e6e..865a9096 100644 --- a/test-suites/test-lp/helpers/make-suite.ts +++ b/test-suites/test-lp/helpers/make-suite.ts @@ -137,7 +137,7 @@ export async function initializeMakeSuite() { const daiAddress = reservesTokens.find((token) => token.symbol === 'UniDAI')?.tokenAddress; const usdcAddress = reservesTokens.find((token) => token.symbol === 'UniUSDC')?.tokenAddress; const aaveAddress = reservesTokens.find((token) => token.symbol === 'UniAAVEWETH')?.tokenAddress; - const wethAddress = reservesTokens.find((token) => token.symbol === 'UniWETH')?.tokenAddress; + const wethAddress = reservesTokens.find((token) => token.symbol === 'WETH')?.tokenAddress; if (!aDaiAddress || !aWEthAddress) { process.exit(1); diff --git a/test-suites/test-lp/helpers/utils/calculations.ts b/test-suites/test-lp/helpers/utils/calculations.ts index dc77b5db..f137b9ef 100644 --- a/test-suites/test-lp/helpers/utils/calculations.ts +++ b/test-suites/test-lp/helpers/utils/calculations.ts @@ -1237,6 +1237,10 @@ export const calcExpectedInterestRates = ( ): BigNumber[] => { const { reservesParams } = configuration; + // Fixes WETH - UniWETH mock token symbol mismatch + if(reserveSymbol === 'WETH') { + reserveSymbol = 'UniWETH'; + } const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol); const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[ reserveIndex From 655f9751f7f33c4d1df63994413c92ed130f862d Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 8 Feb 2021 11:05:10 -0500 Subject: [PATCH 081/219] Replaced "Uniswap" market name & references with "Lp" --- helpers/configuration.ts | 12 +-- helpers/contracts-helpers.ts | 6 +- helpers/types.ts | 10 +-- markets/{uniswap => lp}/commons.ts | 0 markets/{uniswap => lp}/index.ts | 8 +- markets/{uniswap => lp}/reservesConfigs.ts | 2 +- package-lock.json | 3 +- package.json | 1 + tasks/migrations/uniswap.mainnet.ts | 4 +- test-suites/test-lp/__setup.spec.ts | 26 +++--- test-suites/test-lp/atoken-transfer.spec.ts | 2 +- test-suites/test-lp/configurator.spec.ts | 2 +- .../test-lp/delegation-aware-atoken.spec.ts | 4 +- test-suites/test-lp/helpers/make-suite.ts | 4 +- .../helpers/scenarios/borrow-negatives.json | 16 ++-- .../scenarios/borrow-repay-stable.json | 42 ++++----- .../scenarios/borrow-repay-variable.json | 86 +++++++++---------- .../helpers/scenarios/credit-delegation.json | 28 +++--- .../test-lp/helpers/scenarios/deposit.json | 26 +++--- .../scenarios/rebalance-stable-rate.json | 8 +- .../scenarios/set-use-as-collateral.json | 30 +++---- .../helpers/scenarios/swap-rate-mode.json | 6 +- .../helpers/scenarios/withdraw-negatives.json | 10 +-- .../test-lp/helpers/scenarios/withdraw.json | 26 +++--- .../test-lp/helpers/utils/calculations.ts | 4 +- .../test-lp/liquidation-underlying.spec.ts | 2 +- test-suites/test-lp/scenario.spec.ts | 6 +- .../test-lp/subgraph-scenarios.spec.ts | 6 +- 28 files changed, 191 insertions(+), 189 deletions(-) rename markets/{uniswap => lp}/commons.ts (100%) rename markets/{uniswap => lp}/index.ts (94%) rename markets/{uniswap => lp}/reservesConfigs.ts (99%) diff --git a/helpers/configuration.ts b/helpers/configuration.ts index 13baa35a..a9b780fb 100644 --- a/helpers/configuration.ts +++ b/helpers/configuration.ts @@ -8,7 +8,7 @@ import { } from './types'; import { getParamPerPool } from './contracts-helpers'; import AaveConfig from '../markets/aave'; -import UniswapConfig from '../markets/uniswap'; +import LpConfig from '../markets/lp'; import { CommonsConfig } from '../markets/aave/commons'; import { DRE, filterMapBy } from './misc-utils'; import { tEthereumAddress } from './types'; @@ -18,15 +18,15 @@ import { deployWETHMocked } from './contracts-deployments'; export enum ConfigNames { Commons = 'Commons', Aave = 'Aave', - Uniswap = 'Uniswap', + Lp = 'Lp', } export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => { switch (configName) { case ConfigNames.Aave: return AaveConfig; - case ConfigNames.Uniswap: - return UniswapConfig; + case ConfigNames.Lp: + return LpConfig; case ConfigNames.Commons: return CommonsConfig; default: @@ -44,8 +44,8 @@ export const getReservesConfigByPool = (pool: AavePools): iMultiPoolsAssets( } }; -export const getParamPerPool = ({ proto, uniswap }: iParamsPerPool, pool: AavePools) => { +export const getParamPerPool = ({ proto, lp }: iParamsPerPool, pool: AavePools) => { switch (pool) { case AavePools.proto: return proto; - case AavePools.uniswap: - return uniswap; + case AavePools.lp: + return lp; default: return proto; } diff --git a/helpers/types.ts b/helpers/types.ts index 41eecc09..3e56a1aa 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -22,7 +22,7 @@ export enum EthereumNetworkNames { export enum AavePools { proto = 'proto', - uniswap = 'uniswap', + lp = 'lp', } export enum eContractid { @@ -254,7 +254,7 @@ export type iAavePoolAssets = Pick< | 'ENJ' >; -export type iUniswapPoolAssets = Pick< +export type iLpPoolAssets = Pick< iAssetsWithoutUSD, | 'UniDAI' | 'UniUSDC' @@ -364,7 +364,7 @@ export interface iParamsPerNetwork { export interface iParamsPerPool { [AavePools.proto]: T; - [AavePools.uniswap]: T; + [AavePools.lp]: T; } export interface iBasicDistributionParams { @@ -440,8 +440,8 @@ export interface IAaveConfiguration extends ICommonConfiguration { ReservesConfig: iAavePoolAssets; } -export interface IUniswapConfiguration extends ICommonConfiguration { - ReservesConfig: iUniswapPoolAssets; +export interface ILpConfiguration extends ICommonConfiguration { + ReservesConfig: iLpPoolAssets; } export interface ITokenAddress { [token: string]: tEthereumAddress; diff --git a/markets/uniswap/commons.ts b/markets/lp/commons.ts similarity index 100% rename from markets/uniswap/commons.ts rename to markets/lp/commons.ts diff --git a/markets/uniswap/index.ts b/markets/lp/index.ts similarity index 94% rename from markets/uniswap/index.ts rename to markets/lp/index.ts index 55a5a15d..556eb515 100644 --- a/markets/uniswap/index.ts +++ b/markets/lp/index.ts @@ -1,5 +1,5 @@ import { oneRay, ZERO_ADDRESS } from '../../helpers/constants'; -import { IUniswapConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; +import { ILpConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; import { CommonsConfig } from './commons'; import { @@ -28,9 +28,9 @@ import { // POOL--SPECIFIC PARAMS // ---------------- -export const UniswapConfig: IUniswapConfiguration = { +export const lpConfig: ILpConfiguration = { ...CommonsConfig, - MarketId: 'Uniswap V2 market', + MarketId: 'Aave LP market', ProviderId: 2, ReservesConfig: { UniWETH: strategyWETH, @@ -100,4 +100,4 @@ export const UniswapConfig: IUniswapConfiguration = { }, }; -export default UniswapConfig; +export default lpConfig; diff --git a/markets/uniswap/reservesConfigs.ts b/markets/lp/reservesConfigs.ts similarity index 99% rename from markets/uniswap/reservesConfigs.ts rename to markets/lp/reservesConfigs.ts index 6e1e14a1..d82680cb 100644 --- a/markets/uniswap/reservesConfigs.ts +++ b/markets/lp/reservesConfigs.ts @@ -57,7 +57,7 @@ export const strategyUSDC: IReserveParams = { 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(), + variableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(), stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(), stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(), baseLTVAsCollateral: '8000', diff --git a/package-lock.json b/package-lock.json index f45d303b..bbe177fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8136,7 +8136,8 @@ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "color-name": "1.1.3" + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" } }, "color-convert": { diff --git a/package.json b/package.json index 41430a28..4e5803c6 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "console:fork": "MAINNET_FORK=true hardhat console", "test": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-aave/*.spec.ts", "test-lp": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-lp/*.spec.ts", + "test-lp-scenarios": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-lp/__setup.spec.ts test-suites/test-lp/scenario.spec.ts", "test-scenarios": "npx hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/scenario.spec.ts", "test-repay-with-collateral": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/repay-with-collateral.spec.ts", "test-liquidate-with-collateral": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/flash-liquidation-with-collateral.spec.ts", diff --git a/tasks/migrations/uniswap.mainnet.ts b/tasks/migrations/uniswap.mainnet.ts index 86f3a4c2..9b23a499 100644 --- a/tasks/migrations/uniswap.mainnet.ts +++ b/tasks/migrations/uniswap.mainnet.ts @@ -6,10 +6,10 @@ import {EthereumNetworkNames} from '../../helpers/types'; import {printContracts} from '../../helpers/misc-utils'; import {totalGas} from '../../helpers/gas-tracker'; -task('uniswap:mainnet', 'Deploy development enviroment') +task('lp:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') .setAction(async ({verify}, DRE) => { - const POOL_NAME = ConfigNames.Uniswap; + const POOL_NAME = ConfigNames.Lp; const network = DRE.network.name; await DRE.run('set-DRE'); diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-lp/__setup.spec.ts index 45190ee6..8acdbf33 100644 --- a/test-suites/test-lp/__setup.spec.ts +++ b/test-suites/test-lp/__setup.spec.ts @@ -45,7 +45,7 @@ import { } from '../../helpers/oracles-helpers'; import { DRE, waitForTx } from '../../helpers/misc-utils'; import { initReservesByHelper, configureReservesByHelper } from '../../helpers/init-helpers'; -import UniswapConfig from '../../markets/uniswap'; +import LpConfig from '../../markets/lp'; import { ZERO_ADDRESS } from '../../helpers/constants'; import { getLendingPool, @@ -54,26 +54,26 @@ import { } from '../../helpers/contracts-getters'; import { WETH9Mocked } from '../../types/WETH9Mocked'; -const MOCK_USD_PRICE_IN_WEI = UniswapConfig.ProtocolGlobalParams.MockUsdPriceInWei; -const ALL_ASSETS_INITIAL_PRICES = UniswapConfig.Mocks.AllAssetsInitialPrices; -const USD_ADDRESS = UniswapConfig.ProtocolGlobalParams.UsdAddress; -const MOCK_CHAINLINK_AGGREGATORS_PRICES = UniswapConfig.Mocks.AllAssetsInitialPrices; -const LENDING_RATE_ORACLE_RATES_COMMON = UniswapConfig.LendingRateOracleRatesCommon; +const MOCK_USD_PRICE_IN_WEI = LpConfig.ProtocolGlobalParams.MockUsdPriceInWei; +const ALL_ASSETS_INITIAL_PRICES = LpConfig.Mocks.AllAssetsInitialPrices; +const USD_ADDRESS = LpConfig.ProtocolGlobalParams.UsdAddress; +const MOCK_CHAINLINK_AGGREGATORS_PRICES = LpConfig.Mocks.AllAssetsInitialPrices; +const LENDING_RATE_ORACLE_RATES_COMMON = LpConfig.LendingRateOracleRatesCommon; const deployAllMockTokens = async (deployer: Signer) => { const tokens: { [symbol: string]: MockContract | MintableERC20 | WETH9Mocked } = {}; - const uniswapConfigData = getReservesConfigByPool(AavePools.uniswap); + const lpConfigData = getReservesConfigByPool(AavePools.lp); for (const tokenSymbol of Object.keys(TokenContractId)) { if (tokenSymbol === 'UniWETH') { tokens[tokenSymbol] = await deployWETHMocked(); - await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); + await registerContractInJsonDb('WETH', tokens[tokenSymbol]); continue; } let decimals = 18; - let configData = (uniswapConfigData)[tokenSymbol]; + let configData = (lpConfigData)[tokenSymbol]; if (!configData) { decimals = 18; @@ -96,7 +96,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const mockTokens = await deployAllMockTokens(deployer); - const addressesProvider = await deployLendingPoolAddressesProvider(UniswapConfig.MarketId); + const addressesProvider = await deployLendingPoolAddressesProvider(LpConfig.MarketId); await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin)); //setting users[1] as emergency admin, which is in position 2 in the DRE addresses list @@ -225,7 +225,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { aaveAdmin ); - const reservesParams = getReservesConfigByPool(AavePools.uniswap); + const reservesParams = getReservesConfigByPool(AavePools.lp); const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address); @@ -234,7 +234,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { console.log('Initialize configuration'); - const config = loadPoolConfig(ConfigNames.Uniswap); + const config = loadPoolConfig(ConfigNames.Lp); const treasuryAddress = await getTreasuryAddress(config); @@ -279,7 +279,7 @@ before(async () => { const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; if (MAINNET_FORK) { - await rawBRE.run('uniswap:mainnet'); + await rawBRE.run('lp:mainnet'); } else { console.log('-> Deploying test environment...'); await buildTestEnv(deployer, secondaryWallet); diff --git a/test-suites/test-lp/atoken-transfer.spec.ts b/test-suites/test-lp/atoken-transfer.spec.ts index 78bbed8c..268302e3 100644 --- a/test-suites/test-lp/atoken-transfer.spec.ts +++ b/test-suites/test-lp/atoken-transfer.spec.ts @@ -4,7 +4,7 @@ import { expect } from 'chai'; import { ethers } from 'ethers'; import { RateMode, ProtocolErrors } from '../../helpers/types'; import { makeSuite, TestEnv } from './helpers/make-suite'; -import { CommonsConfig } from '../../markets/uniswap/commons'; +import { CommonsConfig } from '../../markets/lp/commons'; const AAVE_REFERRAL = CommonsConfig.ProtocolGlobalParams.AaveReferral; diff --git a/test-suites/test-lp/configurator.spec.ts b/test-suites/test-lp/configurator.spec.ts index f554e19d..6483b391 100644 --- a/test-suites/test-lp/configurator.spec.ts +++ b/test-suites/test-lp/configurator.spec.ts @@ -2,7 +2,7 @@ import { TestEnv, makeSuite } from './helpers/make-suite'; import { APPROVAL_AMOUNT_LENDING_POOL, RAY } from '../../helpers/constants'; import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; import { ProtocolErrors } from '../../helpers/types'; -import { strategyWETH } from '../../markets/uniswap/reservesConfigs'; +import { strategyWETH } from '../../markets/lp/reservesConfigs'; const { expect } = require('chai'); diff --git a/test-suites/test-lp/delegation-aware-atoken.spec.ts b/test-suites/test-lp/delegation-aware-atoken.spec.ts index ba11ed7f..aeaf4499 100644 --- a/test-suites/test-lp/delegation-aware-atoken.spec.ts +++ b/test-suites/test-lp/delegation-aware-atoken.spec.ts @@ -20,7 +20,7 @@ import { import { DelegationAwareATokenFactory } from '../../types'; import { DelegationAwareAToken } from '../../types/DelegationAwareAToken'; import { MintableDelegationERC20 } from '../../types/MintableDelegationERC20'; -import UniswapConfig from '../../markets/uniswap'; +import LpConfig from '../../markets/lp'; const { parseEther } = ethers.utils; @@ -35,7 +35,7 @@ makeSuite('AToken: underlying delegation', (testEnv: TestEnv) => { delegationERC20 = await deployMintableDelegationERC20(['DEL', 'DEL', '18']); delegationAToken = await deployDelegationAwareAToken( - [pool.address, delegationERC20.address, await getTreasuryAddress(UniswapConfig), ZERO_ADDRESS, 'aDEL', 'aDEL'], + [pool.address, delegationERC20.address, await getTreasuryAddress(LpConfig), ZERO_ADDRESS, 'aDEL', 'aDEL'], false ); diff --git a/test-suites/test-lp/helpers/make-suite.ts b/test-suites/test-lp/helpers/make-suite.ts index 865a9096..fd78ae6f 100644 --- a/test-suites/test-lp/helpers/make-suite.ts +++ b/test-suites/test-lp/helpers/make-suite.ts @@ -36,7 +36,7 @@ import { getParamPerNetwork } from '../../../helpers/contracts-helpers'; import { WETH9Mocked } from '../../../types/WETH9Mocked'; import { WETHGateway } from '../../../types/WETHGateway'; import { solidity } from 'ethereum-waffle'; -import { UniswapConfig } from '../../../markets/uniswap'; +import { lpConfig } from '../../../markets/lp'; import { FlashLiquidationAdapter } from '../../../types'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { usingTenderly } from '../../../helpers/tenderly-utils'; @@ -118,7 +118,7 @@ export async function initializeMakeSuite() { if (process.env.MAINNET_FORK === 'true') { testEnv.registry = await getLendingPoolAddressesProviderRegistry( - getParamPerNetwork(UniswapConfig.ProviderRegistry, eEthereumNetwork.main) + getParamPerNetwork(lpConfig.ProviderRegistry, eEthereumNetwork.main) ); } else { testEnv.registry = await getLendingPoolAddressesProviderRegistry(); diff --git a/test-suites/test-lp/helpers/scenarios/borrow-negatives.json b/test-suites/test-lp/helpers/scenarios/borrow-negatives.json index 811b5ed6..6ab95c87 100644 --- a/test-suites/test-lp/helpers/scenarios/borrow-negatives.json +++ b/test-suites/test-lp/helpers/scenarios/borrow-negatives.json @@ -3,7 +3,7 @@ "description": "Test cases for the deposit function.", "stories": [ { - "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 UNIWETH as collateral and tries to borrow 100 UNIDAI with rate mode NONE (revert expected)", + "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 UNIDAI with rate mode NONE (revert expected)", "actions": [ { "name": "mint", @@ -34,7 +34,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -43,7 +43,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -51,7 +51,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -71,7 +71,7 @@ ] }, { - "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 UNIWETH as collateral and tries to borrow 100 UNIDAI with an invalid rate mode (revert expected)", + "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 UNIDAI with an invalid rate mode (revert expected)", "actions": [ { "name": "mint", @@ -102,7 +102,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -111,7 +111,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -119,7 +119,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json b/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json index 40b96803..4f12eb86 100644 --- a/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json +++ b/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json @@ -3,7 +3,7 @@ "description": "Test cases for the borrow function, stable mode.", "stories": [ { - "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 UNIWETH as collateral and borrows 100 UNIDAI at stable rate", + "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 WETH as collateral and borrows 100 UNIDAI at stable rate", "actions": [ { "name": "mint", @@ -34,7 +34,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -43,7 +43,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -51,7 +51,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" @@ -221,7 +221,7 @@ ] }, { - "description": "User 0 deposits 1000 UNIDAI, user 1,2,3,4 deposit 1 UNIWETH each and borrow 100 UNIDAI at stable rate. Everything is repaid, user 0 withdraws", + "description": "User 0 deposits 1000 UNIDAI, user 1,2,3,4 deposit 1 WETH each and borrow 100 UNIDAI at stable rate. Everything is repaid, user 0 withdraws", "actions": [ { "name": "mint", @@ -252,7 +252,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -261,7 +261,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -269,7 +269,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -289,7 +289,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "2" }, @@ -298,7 +298,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "2" }, "expected": "success" @@ -306,7 +306,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "2" }, @@ -326,7 +326,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "3" }, @@ -335,7 +335,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "3" }, "expected": "success" @@ -343,7 +343,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "3" }, @@ -363,7 +363,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "4" }, @@ -372,7 +372,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "4" }, "expected": "success" @@ -380,7 +380,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "4" }, @@ -525,7 +525,7 @@ ] }, { - "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 2 UNIWETH and borrow 100 UNIDAI at stable rate first, then 100 UNIDAI at variable rate, repays everything. User 0 withdraws", + "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 2 WETH and borrow 100 UNIDAI at stable rate first, then 100 UNIDAI at variable rate, repays everything. User 0 withdraws", "actions": [ { "name": "mint", @@ -556,7 +556,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "2", "user": "1" }, @@ -565,7 +565,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -573,7 +573,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "2", "user": "1" }, diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json b/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json index dd5936f9..482e337c 100644 --- a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json +++ b/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json @@ -34,7 +34,7 @@ ] }, { - "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 UNIWETH as collateral and borrows 100 UNIDAI at variable rate", + "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 WETH as collateral and borrows 100 UNIDAI at variable rate", "actions": [ { "name": "mint", @@ -65,7 +65,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -74,7 +74,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -82,7 +82,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -203,7 +203,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "-1", "user": "1" }, @@ -212,12 +212,12 @@ ] }, { - "description": "User 2 deposits a small amount of UNIWETH to account for rounding errors", + "description": "User 2 deposits a small amount of WETH to account for rounding errors", "actions": [ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "0.001", "user": "2" }, @@ -226,7 +226,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "2" }, "expected": "success" @@ -234,7 +234,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "0.001", "user": "2" }, @@ -243,12 +243,12 @@ ] }, { - "description": "User 0 deposits 1 UNIWETH, user 1 deposits 100 UNILINKWETH as collateral and borrows 0.5 WETH at variable rate", + "description": "User 0 deposits 1 WETH, user 1 deposits 100 UNILINKWETH as collateral and borrows 0.5 WETH at variable rate", "actions": [ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "0" }, @@ -257,7 +257,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "0" }, "expected": "success" @@ -265,7 +265,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "0" }, @@ -301,7 +301,7 @@ { "name": "borrow", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "0.5", "borrowRateMode": "variable", "user": "1", @@ -317,7 +317,7 @@ { "name": "repay", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "0", "user": "1", "onBehalfOf": "1", @@ -334,7 +334,7 @@ { "name": "repay", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "-1", "user": "2", "borrowRateMode": "variable", @@ -346,12 +346,12 @@ ] }, { - "description": "User 3 repays a small amount of UNIWETH on behalf of user 1", + "description": "User 3 repays a small amount of WETH on behalf of user 1", "actions": [ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "3" }, @@ -360,7 +360,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "3" }, "expected": "success" @@ -368,7 +368,7 @@ { "name": "repay", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "0.2", "user": "3", "borrowRateMode": "variable", @@ -379,12 +379,12 @@ ] }, { - "description": "User 1 repays the UNIWETH borrow after one year", + "description": "User 1 repays the WETH borrow after one year", "actions": [ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "2" }, @@ -393,7 +393,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "2" }, "expected": "success" @@ -401,7 +401,7 @@ { "name": "repay", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "-1", "borrowRateMode": "variable", "user": "1", @@ -412,12 +412,12 @@ ] }, { - "description": "User 0 withdraws the deposited UNIWETH plus interest", + "description": "User 0 withdraws the deposited WETH plus interest", "actions": [ { "name": "withdraw", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "-1", "user": "0" }, @@ -472,7 +472,7 @@ ] }, { - "description": "User 0 deposits 1000 UNIUSDC, user 1 deposits 1 UNIWETH as collateral and borrows 100 UNIUSDC at variable rate", + "description": "User 0 deposits 1000 UNIUSDC, user 1 deposits 1 WETH as collateral and borrows 100 UNIUSDC at variable rate", "actions": [ { "name": "mint", @@ -503,7 +503,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -512,7 +512,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -520,7 +520,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -609,7 +609,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "-1", "user": "1" }, @@ -665,7 +665,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "0.1", "user": "1" }, @@ -674,7 +674,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -682,7 +682,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "0.1", "user": "3" }, @@ -707,7 +707,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "-1", "user": "3" }, @@ -763,7 +763,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "3" }, @@ -772,7 +772,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -780,7 +780,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "0.1", "user": "3" }, @@ -805,7 +805,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "-1", "user": "3" }, @@ -814,7 +814,7 @@ ] }, { - "description": "User 0 deposits 1000 UNIDAI, user 6 deposits 2 UNIWETH and borrow 100 UNIDAI at variable rate first, then 100 UNIDAI at stable rate, repays everything. User 0 withdraws", + "description": "User 0 deposits 1000 UNIDAI, user 6 deposits 2 WETH and borrow 100 UNIDAI at variable rate first, then 100 UNIDAI at stable rate, repays everything. User 0 withdraws", "actions": [ { "name": "mint", @@ -845,7 +845,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "2", "user": "6" }, @@ -854,7 +854,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "6" }, "expected": "success" @@ -862,7 +862,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "2", "user": "6" }, diff --git a/test-suites/test-lp/helpers/scenarios/credit-delegation.json b/test-suites/test-lp/helpers/scenarios/credit-delegation.json index b1bf7479..6b9ece7e 100644 --- a/test-suites/test-lp/helpers/scenarios/credit-delegation.json +++ b/test-suites/test-lp/helpers/scenarios/credit-delegation.json @@ -3,12 +3,12 @@ "description": "Test cases for the credit delegation related functions.", "stories": [ { - "description": "User 3 deposits 1000 UNIWETH. User 0 deposits 1000 UNIDAI, user 0 delegates borrowing of 1 UNIWETH on variable to user 4, user 4 borrows 1 UNIWETH variable on behalf of user 0", + "description": "User 3 deposits 1000 WETH. User 0 deposits 1000 UNIDAI, user 0 delegates borrowing of 1 WETH on variable to user 4, user 4 borrows 1 WETH variable on behalf of user 0", "actions": [ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1000", "user": "3" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "3" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1000", "user": "3" }, @@ -60,7 +60,7 @@ { "name": "delegateBorrowAllowance", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "2", "user": "0", "borrowRateMode": "variable", @@ -71,7 +71,7 @@ { "name": "borrow", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "4", "onBehalfOf": "0", @@ -82,12 +82,12 @@ ] }, { - "description": "User 4 trying to borrow 1 UNIWETH stable on behalf of user 0, revert expected", + "description": "User 4 trying to borrow 1 WETH stable on behalf of user 0, revert expected", "actions": [ { "name": "borrow", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "4", "onBehalfOf": "0", @@ -99,12 +99,12 @@ ] }, { - "description": "User 0 delegates borrowing of 1 UNIWETH to user 4, user 4 borrows 3 UNIWETH variable on behalf of user 0, revert expected", + "description": "User 0 delegates borrowing of 1 WETH to user 4, user 4 borrows 3 WETH variable on behalf of user 0, revert expected", "actions": [ { "name": "delegateBorrowAllowance", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "0", "borrowRateMode": "variable", @@ -115,7 +115,7 @@ { "name": "borrow", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "3", "user": "4", "onBehalfOf": "0", @@ -127,12 +127,12 @@ ] }, { - "description": "User 0 delegates borrowing of 1 UNIWETH on stable to user 2, user 2 borrows 1 UNIWETH stable on behalf of user 0", + "description": "User 0 delegates borrowing of 1 WETH on stable to user 2, user 2 borrows 1 WETH stable on behalf of user 0", "actions": [ { "name": "delegateBorrowAllowance", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "0", "borrowRateMode": "stable", @@ -143,7 +143,7 @@ { "name": "borrow", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "2", "onBehalfOf": "0", diff --git a/test-suites/test-lp/helpers/scenarios/deposit.json b/test-suites/test-lp/helpers/scenarios/deposit.json index a741fe6f..385518b8 100644 --- a/test-suites/test-lp/helpers/scenarios/deposit.json +++ b/test-suites/test-lp/helpers/scenarios/deposit.json @@ -127,12 +127,12 @@ ] }, { - "description": "User 0 deposits 1 UNIWETH in an empty reserve", + "description": "User 0 deposits 1 WETH in an empty reserve", "actions": [ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "0" }, @@ -141,7 +141,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "0" }, "expected": "success" @@ -149,7 +149,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "0" }, @@ -158,12 +158,12 @@ ] }, { - "description": "User 1 deposits 1 UNIWETH after user 0", + "description": "User 1 deposits 1 WETH after user 0", "actions": [ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -173,7 +173,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -181,7 +181,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -190,12 +190,12 @@ ] }, { - "description": "User 1 deposits 0 UNIWETH (revert expected)", + "description": "User 1 deposits 0 WETH (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "0" }, @@ -204,7 +204,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "0", "user": "1" }, @@ -229,7 +229,7 @@ ] }, { - "description": "User 1 deposits 100 UNIDAI on behalf of user 2, user 2 tries to borrow 0.1 UNIWETH", + "description": "User 1 deposits 100 UNIDAI on behalf of user 2, user 2 tries to borrow 0.1 WETH", "actions": [ { "name": "mint", @@ -253,7 +253,7 @@ { "name": "borrow", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "0.1", "borrowRateMode": "variable", "user": "2" diff --git a/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json b/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json index 8d6e4b99..32c7c9bb 100644 --- a/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json +++ b/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json @@ -18,7 +18,7 @@ ] }, { - "description": "User 0 deposits 1000 UNIUSDC, user 1 deposits 7 UNIWETH, borrows 250 UNIUSDC at a stable rate, user 0 rebalances user 1 (revert expected)", + "description": "User 0 deposits 1000 UNIUSDC, user 1 deposits 7 WETH, borrows 250 UNIUSDC at a stable rate, user 0 rebalances user 1 (revert expected)", "actions": [ { "name": "mint", @@ -49,7 +49,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "7", "user": "1" }, @@ -58,7 +58,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -66,7 +66,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "7", "user": "1" }, diff --git a/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json b/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json index f573fe81..71a3f860 100644 --- a/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json +++ b/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json @@ -43,12 +43,12 @@ ] }, { - "description": "User 1 Deposits 2 UNIWETH, disables UNIWETH as collateral, borrows 400 UNIDAI (revert expected)", + "description": "User 1 Deposits 2 WETH, disables WETH as collateral, borrows 400 UNIDAI (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "2", "user": "1" }, @@ -57,7 +57,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -65,7 +65,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "2", "user": "1" }, @@ -74,7 +74,7 @@ { "name": "setUseAsCollateral", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1", "useAsCollateral": "false" }, @@ -94,12 +94,12 @@ ] }, { - "description": "User 1 enables UNIWETH as collateral, borrows 400 UNIDAI", + "description": "User 1 enables WETH as collateral, borrows 400 UNIDAI", "actions": [ { "name": "setUseAsCollateral", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1", "useAsCollateral": "true" }, @@ -118,12 +118,12 @@ ] }, { - "description": "User 1 disables UNIWETH as collateral (revert expected)", + "description": "User 1 disables WETH as collateral (revert expected)", "actions": [ { "name": "setUseAsCollateral", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1", "useAsCollateral": "false" }, @@ -133,7 +133,7 @@ ] }, { - "description": "User 1 Deposits 10 UNILINKWETH, disables UNIWETH as collateral. Should revert as 10 UNILINKWETH are not enough to cover the debt (revert expected)", + "description": "User 1 Deposits 10 UNILINKWETH, disables WETH as collateral. Should revert as 10 UNILINKWETH are not enough to cover the debt (revert expected)", "actions": [ { "name": "mint", @@ -164,7 +164,7 @@ { "name": "setUseAsCollateral", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1", "useAsCollateral": "false" }, @@ -173,7 +173,7 @@ ] }, { - "description": "User 1 Deposits 640 more UNILINKWETH (enough to cover the UNIDAI debt), disables UNIWETH as collateral", + "description": "User 1 Deposits 640 more UNILINKWETH (enough to cover the UNIDAI debt), disables WETH as collateral", "actions": [ { "name": "mint", @@ -196,7 +196,7 @@ { "name": "setUseAsCollateral", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1", "useAsCollateral": "false" }, @@ -219,12 +219,12 @@ ] }, { - "description": "User 1 reenables UNIWETH as collateral", + "description": "User 1 reenables WETH as collateral", "actions": [ { "name": "setUseAsCollateral", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1", "useAsCollateral": "true" }, diff --git a/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json b/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json index 2b175236..dcd7ac98 100644 --- a/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json +++ b/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json @@ -64,7 +64,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "2", "user": "1" }, @@ -73,7 +73,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -81,7 +81,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "2", "user": "1" }, diff --git a/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json b/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json index 5eca78d4..209a7de8 100644 --- a/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json +++ b/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json @@ -60,12 +60,12 @@ ] }, { - "description": "Users 1 deposits 1 UNIWETH, borrows 100 UNIDAI, tries to redeem the 1 UNIWETH deposited (revert expected)", + "description": "Users 1 deposits 1 WETH, borrows 100 UNIDAI, tries to redeem the 1 WETH deposited (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -74,7 +74,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -82,7 +82,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -101,7 +101,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "-1", "user": "1" }, diff --git a/test-suites/test-lp/helpers/scenarios/withdraw.json b/test-suites/test-lp/helpers/scenarios/withdraw.json index 461c7db2..ed0d2ff7 100644 --- a/test-suites/test-lp/helpers/scenarios/withdraw.json +++ b/test-suites/test-lp/helpers/scenarios/withdraw.json @@ -121,12 +121,12 @@ ] }, { - "description": "User 0 Deposits 1 UNIWETH in an empty reserve", + "description": "User 0 Deposits 1 WETH in an empty reserve", "actions": [ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "0" }, @@ -135,7 +135,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "0" }, "expected": "success" @@ -143,7 +143,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "0" }, @@ -152,12 +152,12 @@ ] }, { - "description": "User 0 withdraws half of the deposited UNIWETH", + "description": "User 0 withdraws half of the deposited WETH", "actions": [ { "name": "withdraw", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "0.5", "user": "0" }, @@ -171,7 +171,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "-1", "user": "0" }, @@ -238,7 +238,7 @@ ] }, { - "description": "Users 0 deposits 1000 UNIDAI, user 1 Deposit 1000 UNIUSDC and 1 UNIWETH, borrows 100 UNIDAI. User 1 tries to withdraw all the UNIUSDC", + "description": "Users 0 deposits 1000 UNIDAI, user 1 Deposit 1000 UNIUSDC and 1 WETH, borrows 100 UNIDAI. User 1 tries to withdraw all the UNIUSDC", "actions": [ { "name": "deposit", @@ -278,7 +278,7 @@ { "name": "mint", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -287,7 +287,7 @@ { "name": "approve", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "user": "1" }, "expected": "success" @@ -295,7 +295,7 @@ { "name": "deposit", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "1", "user": "1" }, @@ -323,12 +323,12 @@ ] }, { - "description": "Users 1 tries to withdraw 0.05 UNIWETH, which does not bring the HF below 1", + "description": "Users 1 tries to withdraw 0.05 WETH, which does not bring the HF below 1", "actions": [ { "name": "withdraw", "args": { - "reserve": "UNIWETH", + "reserve": "WETH", "amount": "0.05", "user": "1" }, diff --git a/test-suites/test-lp/helpers/utils/calculations.ts b/test-suites/test-lp/helpers/utils/calculations.ts index f137b9ef..f36c0c6a 100644 --- a/test-suites/test-lp/helpers/utils/calculations.ts +++ b/test-suites/test-lp/helpers/utils/calculations.ts @@ -2,7 +2,7 @@ import BigNumber from 'bignumber.js'; import { ONE_YEAR, RAY, MAX_UINT_AMOUNT, PERCENTAGE_FACTOR } from '../../../../helpers/constants'; import { IReserveParams, - iUniswapPoolAssets, + iLpPoolAssets, RateMode, tEthereumAddress, } from '../../../../helpers/types'; @@ -12,7 +12,7 @@ import { ReserveData, UserReserveData } from './interfaces'; export const strToBN = (amount: string): BigNumber => new BigNumber(amount); interface Configuration { - reservesParams: iUniswapPoolAssets; + reservesParams: iLpPoolAssets; } export const configuration: Configuration = {}; diff --git a/test-suites/test-lp/liquidation-underlying.spec.ts b/test-suites/test-lp/liquidation-underlying.spec.ts index 7f557409..0c9c4adf 100644 --- a/test-suites/test-lp/liquidation-underlying.spec.ts +++ b/test-suites/test-lp/liquidation-underlying.spec.ts @@ -7,7 +7,7 @@ import { makeSuite } from './helpers/make-suite'; import { ProtocolErrors, RateMode } from '../../helpers/types'; import { calcExpectedStableDebtTokenBalance } from './helpers/utils/calculations'; import { getUserData } from './helpers/utils/helpers'; -import { CommonsConfig } from '../../markets/uniswap/commons'; +import { CommonsConfig } from '../../markets/lp/commons'; import { parseEther } from 'ethers/lib/utils'; diff --git a/test-suites/test-lp/scenario.spec.ts b/test-suites/test-lp/scenario.spec.ts index 03a485d6..076ae9db 100644 --- a/test-suites/test-lp/scenario.spec.ts +++ b/test-suites/test-lp/scenario.spec.ts @@ -5,7 +5,7 @@ import fs from 'fs'; import BigNumber from 'bignumber.js'; import { makeSuite } from './helpers/make-suite'; import { getReservesConfigByPool } from '../../helpers/configuration'; -import { AavePools, iUniswapPoolAssets, IReserveParams } from '../../helpers/types'; +import { AavePools, iLpPoolAssets, IReserveParams } from '../../helpers/types'; import { executeStory } from './helpers/scenario-engine'; const scenarioFolder = './test/helpers/scenarios/'; @@ -24,8 +24,8 @@ fs.readdirSync(scenarioFolder).forEach((file) => { actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage - calculationsConfiguration.reservesParams = >( - getReservesConfigByPool(AavePools.uniswap) + calculationsConfiguration.reservesParams = >( + getReservesConfigByPool(AavePools.lp) ); }); after('Reset', () => { diff --git a/test-suites/test-lp/subgraph-scenarios.spec.ts b/test-suites/test-lp/subgraph-scenarios.spec.ts index 3aaee4ba..24e119f1 100644 --- a/test-suites/test-lp/subgraph-scenarios.spec.ts +++ b/test-suites/test-lp/subgraph-scenarios.spec.ts @@ -4,7 +4,7 @@ import { configuration as calculationsConfiguration } from './helpers/utils/calc import BigNumber from 'bignumber.js'; import { makeSuite } from './helpers/make-suite'; import { getReservesConfigByPool } from '../../helpers/configuration'; -import { AavePools, iUniswapPoolAssets, IReserveParams } from '../../helpers/types'; +import { AavePools, iLpPoolAssets, IReserveParams } from '../../helpers/types'; import { executeStory } from './helpers/scenario-engine'; makeSuite('Subgraph scenario tests', async (testEnv) => { @@ -18,8 +18,8 @@ makeSuite('Subgraph scenario tests', async (testEnv) => { actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage - calculationsConfiguration.reservesParams = >( - getReservesConfigByPool(AavePools.uniswap) + calculationsConfiguration.reservesParams = >( + getReservesConfigByPool(AavePools.lp) ); }); after('Reset', () => { From 0bf9810158cc11c2b10210bd246723a7d765c0e4 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 8 Feb 2021 11:24:01 -0500 Subject: [PATCH 082/219] Replaced "Uni" prefix with "Lp" for tokens --- helpers/contracts-getters.ts | 4 +- helpers/types.ts | 114 +++++------ markets/aave/commons.ts | 38 ++-- markets/lp/commons.ts | 184 +++++++++--------- markets/lp/index.ts | 88 ++++----- test-suites/test-aave/__setup.spec.ts | 38 ++-- test-suites/test-lp/__setup.spec.ts | 42 ++-- test-suites/test-lp/atoken-transfer.spec.ts | 2 +- test-suites/test-lp/helpers/make-suite.ts | 10 +- .../helpers/scenarios/borrow-negatives.json | 20 +- .../scenarios/borrow-repay-stable.json | 124 ++++++------ .../scenarios/borrow-repay-variable.json | 142 +++++++------- .../helpers/scenarios/credit-delegation.json | 8 +- .../test-lp/helpers/scenarios/deposit.json | 42 ++-- .../scenarios/rebalance-stable-rate.json | 32 +-- .../scenarios/set-use-as-collateral.json | 36 ++-- .../helpers/scenarios/swap-rate-mode.json | 30 +-- .../helpers/scenarios/withdraw-negatives.json | 18 +- .../test-lp/helpers/scenarios/withdraw.json | 60 +++--- .../test-lp/helpers/utils/calculations.ts | 4 +- test-suites/test-lp/stable-token.spec.ts | 2 +- test-suites/test-lp/upgradeability.spec.ts | 12 +- test/__setup.spec.ts | 38 ++-- 23 files changed, 544 insertions(+), 544 deletions(-) diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index 21e61006..aa96553f 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -172,10 +172,10 @@ export const getPairsTokenAggregator = ( }, aggregatorsAddresses: { [tokenSymbol: string]: tEthereumAddress } ): [string[], string[]] => { - const { ETH, USD, WETH, UniWETH, ...assetsAddressesWithoutEth } = allAssetsAddresses; + const { ETH, USD, WETH, LpWETH, ...assetsAddressesWithoutEth } = allAssetsAddresses; const pairs = Object.entries(assetsAddressesWithoutEth).map(([tokenSymbol, tokenAddress]) => { - //if (true/*tokenSymbol !== 'WETH' && tokenSymbol !== 'ETH' && tokenSymbol !== 'UniWETH'*/) { + //if (true/*tokenSymbol !== 'WETH' && tokenSymbol !== 'ETH' && tokenSymbol !== 'LpWETH'*/) { const aggregatorAddressIndex = Object.keys(aggregatorsAddresses).findIndex( (value) => value === tokenSymbol ); diff --git a/helpers/types.ts b/helpers/types.ts index 3e56a1aa..63295895 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -205,25 +205,25 @@ export interface iAssetBase { USD: T; REN: T; ENJ: T; - UniWETH: T; - UniWBTC: T; - UniDAI: T; - UniUSDC: T; - UniUSDT: T; - UniDAIWETH: T; - UniWBTCWETH: T; - UniAAVEWETH: T; - UniBATWETH: T; - UniUSDCDAI: T; - UniCRVWETH: T; - UniLINKWETH: T; - UniMKRWETH: T; - UniRENWETH: T; - UniSNXWETH: T; - UniUNIWETH: T; - UniUSDCWETH: T; - UniWBTCUSDC: T; - UniYFIWETH: T; + LpWETH: T; + LpWBTC: T; + LpDAI: T; + LpUSDC: T; + LpUSDT: T; + LpDAIWETH: T; + LpWBTCWETH: T; + LpAAVEWETH: T; + LpBATWETH: T; + LpUSDCDAI: T; + LpCRVWETH: T; + LpLINKWETH: T; + LpMKRWETH: T; + LpRENWETH: T; + LpSNXWETH: T; + LpUNIWETH: T; + LpUSDCWETH: T; + LpWBTCUSDC: T; + LpYFIWETH: T; } export type iAssetsWithoutETH = Omit, 'ETH'>; @@ -256,25 +256,25 @@ export type iAavePoolAssets = Pick< export type iLpPoolAssets = Pick< iAssetsWithoutUSD, - | 'UniDAI' - | 'UniUSDC' - | 'UniUSDT' - | 'UniWBTC' - | 'UniWETH' - | 'UniDAIWETH' - | 'UniWBTCWETH' - | 'UniAAVEWETH' - | 'UniBATWETH' - | 'UniUSDCDAI' - | 'UniCRVWETH' - | 'UniLINKWETH' - | 'UniMKRWETH' - | 'UniRENWETH' - | 'UniSNXWETH' - | 'UniUNIWETH' - | 'UniUSDCWETH' - | 'UniWBTCUSDC' - | 'UniYFIWETH' + | 'LpDAI' + | 'LpUSDC' + | 'LpUSDT' + | 'LpWBTC' + | 'LpWETH' + | 'LpDAIWETH' + | 'LpWBTCWETH' + | 'LpAAVEWETH' + | 'LpBATWETH' + | 'LpUSDCDAI' + | 'LpCRVWETH' + | 'LpLINKWETH' + | 'LpMKRWETH' + | 'LpRENWETH' + | 'LpSNXWETH' + | 'LpUNIWETH' + | 'LpUSDCWETH' + | 'LpWBTCUSDC' + | 'LpYFIWETH' >; export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; @@ -305,25 +305,25 @@ export enum TokenContractId { YFI = 'YFI', UNI = 'UNI', ENJ = 'ENJ', - UniWETH = 'UniWETH', - UniWBTC = 'UniWBTC', - UniDAI = 'UniDAI', - UniUSDC = 'UniUSDC', - UniUSDT = 'UniUSDT', - UniDAIWETH = 'UniDAIWETH', - UniWBTCWETH = 'UniWBTCWETH', - UniAAVEWETH = 'UniAAVEWETH', - UniBATWETH = 'UniBATWETH', - UniUSDCDAI = 'UniUSDCDAI', - UniCRVWETH = 'UniCRVWETH', - UniLINKWETH = 'UniLINKWETH', - UniMKRWETH = 'UniMKRWETH', - UniRENWETH = 'UniRENWETH', - UniSNXWETH = 'UniSNXWETH', - UniUNIWETH = 'UniUNIWETH', - UniUSDCWETH = 'UniUSDCWETH', - UniWBTCUSDC = 'UniWBTCUSDC', - UniYFIWETH = 'UniYFIWETH', + LpWETH = 'LpWETH', + LpWBTC = 'LpWBTC', + LpDAI = 'LpDAI', + LpUSDC = 'LpUSDC', + LpUSDT = 'LpUSDT', + LpDAIWETH = 'LpDAIWETH', + LpWBTCWETH = 'LpWBTCWETH', + LpAAVEWETH = 'LpAAVEWETH', + LpBATWETH = 'LpBATWETH', + LpUSDCDAI = 'LpUSDCDAI', + LpCRVWETH = 'LpCRVWETH', + LpLINKWETH = 'LpLINKWETH', + LpMKRWETH = 'LpMKRWETH', + LpRENWETH = 'LpRENWETH', + LpSNXWETH = 'LpSNXWETH', + LpUNIWETH = 'LpUNIWETH', + LpUSDCWETH = 'LpUSDCWETH', + LpWBTCUSDC = 'LpWBTCUSDC', + LpYFIWETH = 'LpYFIWETH', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index be9ae7e5..69d820ab 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -23,25 +23,25 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), - UniDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - UniUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - UniUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - UniWBTC: oneEther.multipliedBy('47.332685').toFixed(), - UniWETH: oneEther.toFixed(), - UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), - UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), - UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), - UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), - UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + LpUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), + LpWETH: oneEther.toFixed(), + LpDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), + LpBATWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), + LpCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), + LpMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpRENWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), + LpYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index a74338bc..aaca1cf0 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -23,25 +23,25 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), - UniDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - UniUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - UniUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - UniWBTC: oneEther.multipliedBy('47.332685').toFixed(), - UniWETH: oneEther.toFixed(), - UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), - UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), - UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), - UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), - UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + LpUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), + LpWETH: oneEther.toFixed(), + LpDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), + LpBATWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), + LpCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), + LpMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpRENWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), + LpYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; // ---------------- @@ -71,61 +71,61 @@ export const CommonsConfig: ICommonConfiguration = { }, // TODO: reorg alphabetically, checking the reason of tests failing LendingRateOracleRatesCommon: { - UniWETH: { + LpWETH: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - UniDAI: { + LpDAI: { borrowRate: oneRay.multipliedBy(0.039).toFixed(), }, - UniUSDC: { + LpUSDC: { borrowRate: oneRay.multipliedBy(0.039).toFixed(), }, - UniUSDT: { + LpUSDT: { borrowRate: oneRay.multipliedBy(0.035).toFixed(), }, - UniWBTC: { + LpWBTC: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - UniDAIWETH: { + LpDAIWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniWBTCWETH: { + LpWBTCWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniAAVEWETH:{ + LpAAVEWETH:{ borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniBATWETH: { + LpBATWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniUSDCDAI: { + LpUSDCDAI: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniCRVWETH: { + LpCRVWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniLINKWETH: { + LpLINKWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniMKRWETH: { + LpMKRWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniRENWETH: { + LpRENWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniSNXWETH: { + LpSNXWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniUNIWETH: { + LpUNIWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniUSDCWETH: { + LpUSDCWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniWBTCUSDC: { + LpWBTCUSDC: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniYFIWETH: { + LpYFIWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, }, @@ -214,68 +214,68 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.buidlerevm]: {}, [EthereumNetwork.kovan]: { - UniUSDT: '0x0bF499444525a23E7Bb61997539725cA2e928138', - UniWBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', - UniUSDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', - UniDAI:'0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', - UniDAIWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', // Mock oracles - UniWBTCWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - UniAAVEWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - UniBATWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - UniUSDCDAI: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - UniCRVWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - UniLINKWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - UniMKRWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - UniRENWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - UniSNXWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - UniUNIWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - UniUSDCWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - UniWBTCUSDC: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - UniYFIWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpUSDT: '0x0bF499444525a23E7Bb61997539725cA2e928138', + LpWBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', + LpUSDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', + LpDAI:'0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', + LpDAIWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', // Mock oracles + LpWBTCWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpAAVEWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpBATWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpUSDCDAI: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpCRVWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpLINKWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpMKRWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpRENWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpSNXWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpUNIWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpUSDCWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpWBTCUSDC: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpYFIWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [EthereumNetwork.ropsten]: { }, [EthereumNetwork.main]: { - UniUSDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', - UniWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', - UniUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', - UniDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', - UniDAIWETH: '0xf4071801C4421Db7e63DaC15B9432e50C44a7F42', - UniWBTCWETH: ZERO_ADDRESS, - UniAAVEWETH: ZERO_ADDRESS, - UniBATWETH: ZERO_ADDRESS, - UniUSDCDAI: ZERO_ADDRESS, - UniCRVWETH: ZERO_ADDRESS, - UniLINKWETH: ZERO_ADDRESS, - UniMKRWETH: ZERO_ADDRESS, - UniRENWETH: ZERO_ADDRESS, - UniSNXWETH: ZERO_ADDRESS, - UniUNIWETH: ZERO_ADDRESS, - UniUSDCWETH: ZERO_ADDRESS, - UniWBTCUSDC: ZERO_ADDRESS, - UniYFIWETH: ZERO_ADDRESS, + LpUSDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', + LpWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', + LpUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', + LpDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', + LpDAIWETH: '0xf4071801C4421Db7e63DaC15B9432e50C44a7F42', + LpWBTCWETH: ZERO_ADDRESS, + LpAAVEWETH: ZERO_ADDRESS, + LpBATWETH: ZERO_ADDRESS, + LpUSDCDAI: ZERO_ADDRESS, + LpCRVWETH: ZERO_ADDRESS, + LpLINKWETH: ZERO_ADDRESS, + LpMKRWETH: ZERO_ADDRESS, + LpRENWETH: ZERO_ADDRESS, + LpSNXWETH: ZERO_ADDRESS, + LpUNIWETH: ZERO_ADDRESS, + LpUSDCWETH: ZERO_ADDRESS, + LpWBTCUSDC: ZERO_ADDRESS, + LpYFIWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [EthereumNetwork.tenderlyMain]: { - UniUSDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', - UniWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', - UniUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', - UniDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', - UniDAIWETH: ZERO_ADDRESS, - UniWBTCWETH: ZERO_ADDRESS, - UniAAVEWETH: ZERO_ADDRESS, - UniBATWETH: ZERO_ADDRESS, - UniUSDCDAI: ZERO_ADDRESS, - UniCRVWETH: ZERO_ADDRESS, - UniLINKWETH: ZERO_ADDRESS, - UniMKRWETH: ZERO_ADDRESS, - UniRENWETH: ZERO_ADDRESS, - UniSNXWETH: ZERO_ADDRESS, - UniUNIWETH: ZERO_ADDRESS, - UniUSDCWETH: ZERO_ADDRESS, - UniWBTCUSDC: ZERO_ADDRESS, - UniYFIWETH: ZERO_ADDRESS, + LpUSDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', + LpWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', + LpUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', + LpDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', + LpDAIWETH: ZERO_ADDRESS, + LpWBTCWETH: ZERO_ADDRESS, + LpAAVEWETH: ZERO_ADDRESS, + LpBATWETH: ZERO_ADDRESS, + LpUSDCDAI: ZERO_ADDRESS, + LpCRVWETH: ZERO_ADDRESS, + LpLINKWETH: ZERO_ADDRESS, + LpMKRWETH: ZERO_ADDRESS, + LpRENWETH: ZERO_ADDRESS, + LpSNXWETH: ZERO_ADDRESS, + LpUNIWETH: ZERO_ADDRESS, + LpUSDCWETH: ZERO_ADDRESS, + LpWBTCUSDC: ZERO_ADDRESS, + LpYFIWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, }, diff --git a/markets/lp/index.ts b/markets/lp/index.ts index 556eb515..55d44e86 100644 --- a/markets/lp/index.ts +++ b/markets/lp/index.ts @@ -33,62 +33,62 @@ export const lpConfig: ILpConfiguration = { MarketId: 'Aave LP market', ProviderId: 2, ReservesConfig: { - UniWETH: strategyWETH, - UniDAI: strategyDAI, - UniUSDC: strategyUSDC, - UniUSDT: strategyUSDT, - UniWBTC: strategyWBTC, - UniDAIWETH: strategyDAIWETH, - UniWBTCWETH: strategyWBTCWETH, - UniAAVEWETH: strategyAAVEWETH, - UniBATWETH: strategyBATWETH, - UniUSDCDAI: strategyUSDCDAI, - UniCRVWETH: strategyCRVWETH, - UniLINKWETH: strategyLINKWETH, - UniMKRWETH: strategyMKRWETH, - UniRENWETH: strategyRENWETH, - UniSNXWETH: strategySNXWETH, - UniUNIWETH: strategyUNIWETH, - UniUSDCWETH: strategyUSDCWETH, - UniWBTCUSDC: strategyWBTCUSDC, - UniYFIWETH: strategyYFIWETH, + LpWETH: strategyWETH, + LpDAI: strategyDAI, + LpUSDC: strategyUSDC, + LpUSDT: strategyUSDT, + LpWBTC: strategyWBTC, + LpDAIWETH: strategyDAIWETH, + LpWBTCWETH: strategyWBTCWETH, + LpAAVEWETH: strategyAAVEWETH, + LpBATWETH: strategyBATWETH, + LpUSDCDAI: strategyUSDCDAI, + LpCRVWETH: strategyCRVWETH, + LpLINKWETH: strategyLINKWETH, + LpMKRWETH: strategyMKRWETH, + LpRENWETH: strategyRENWETH, + LpSNXWETH: strategySNXWETH, + LpUNIWETH: strategyUNIWETH, + LpUSDCWETH: strategyUSDCWETH, + LpWBTCUSDC: strategyWBTCUSDC, + LpYFIWETH: strategyYFIWETH, }, ReserveAssets: { [eEthereumNetwork.buidlerevm]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.coverage]: {}, [EthereumNetwork.kovan]: { - UniDAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', - UniUSDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', - UniUSDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', - UniWBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', - UniWETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', - UniDAIWETH: '0x7d3A67ab574abD3F9849e5fcDa48c19939d032b4', + LpDAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', + LpUSDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', + LpUSDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', + LpWBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', + LpWETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', + LpDAIWETH: '0x7d3A67ab574abD3F9849e5fcDa48c19939d032b4', uniWBTCWETH: '0x342e78bf229Cd2a750E80D7D7c2C185455979b91', // Other assets }, [EthereumNetwork.ropsten]: { }, [EthereumNetwork.main]: { - UniDAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - UniUSDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - UniUSDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', - UniWBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', - UniWETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - UniDAIWETH: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', - UniWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', - UniAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f', - UniBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838', - UniUSDCDAI: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', - UniCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE', - UniLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974', - UniMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225', - UniRENWETH: '0x8Bd1661Da98EBDd3BD080F0bE4e6d9bE8cE9858c', - UniSNXWETH: '0x43AE24960e5534731Fc831386c07755A2dc33D47', - UniUNIWETH: '0xd3d2E2692501A5c9Ca623199D38826e513033a17', - UniUSDCWETH: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc', - UniWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416', - UniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', + LpDAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + LpUSDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + LpUSDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + LpWBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + LpWETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + LpDAIWETH: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', + LpWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', + LpAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f', + LpBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838', + LpUSDCDAI: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', + LpCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE', + LpLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974', + LpMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225', + LpRENWETH: '0x8Bd1661Da98EBDd3BD080F0bE4e6d9bE8cE9858c', + LpSNXWETH: '0x43AE24960e5534731Fc831386c07755A2dc33D47', + LpUNIWETH: '0xd3d2E2692501A5c9Ca623199D38826e513033a17', + LpUSDCWETH: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc', + LpWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416', + LpYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', }, [EthereumNetwork.tenderlyMain]: { DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index c099facd..bd284dee 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -165,25 +165,25 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { REN: mockTokens.REN.address, UNI: mockTokens.UNI.address, ENJ: mockTokens.ENJ.address, - UniDAI: mockTokens.UniDAI.address, - UniUSDC: mockTokens.UniUSDC.address, - UniUSDT: mockTokens.UniUSDT.address, - UniWBTC: mockTokens.UniWBTC.address, - UniWETH: mockTokens.UniWETH.address, - UniDAIWETH: mockTokens.UniDAIWETH.address, - UniWBTCWETH: mockTokens.UniWBTCWETH.address, - UniAAVEWETH: mockTokens.UniAAVEWETH.address, - UniBATWETH: mockTokens.UniBATWETH.address, - UniUSDCDAI: mockTokens.UniUSDCDAI.address, - UniCRVWETH: mockTokens.UniCRVWETH.address, - UniLINKWETH: mockTokens.UniLINKWETH.address, - UniMKRWETH: mockTokens.UniMKRWETH.address, - UniRENWETH: mockTokens.UniRENWETH.address, - UniSNXWETH: mockTokens.UniSNXWETH.address, - UniUNIWETH: mockTokens.UniUNIWETH.address, - UniUSDCWETH: mockTokens.UniUSDCWETH.address, - UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, - UniYFIWETH: mockTokens.UniYFIWETH.address, + LpDAI: mockTokens.LpDAI.address, + LpUSDC: mockTokens.LpUSDC.address, + LpUSDT: mockTokens.LpUSDT.address, + LpWBTC: mockTokens.LpWBTC.address, + LpWETH: mockTokens.LpWETH.address, + LpDAIWETH: mockTokens.LpDAIWETH.address, + LpWBTCWETH: mockTokens.LpWBTCWETH.address, + LpAAVEWETH: mockTokens.LpAAVEWETH.address, + LpBATWETH: mockTokens.LpBATWETH.address, + LpUSDCDAI: mockTokens.LpUSDCDAI.address, + LpCRVWETH: mockTokens.LpCRVWETH.address, + LpLINKWETH: mockTokens.LpLINKWETH.address, + LpMKRWETH: mockTokens.LpMKRWETH.address, + LpRENWETH: mockTokens.LpRENWETH.address, + LpSNXWETH: mockTokens.LpSNXWETH.address, + LpUNIWETH: mockTokens.LpUNIWETH.address, + LpUSDCWETH: mockTokens.LpUSDCWETH.address, + LpWBTCUSDC: mockTokens.LpWBTCUSDC.address, + LpYFIWETH: mockTokens.LpYFIWETH.address, USD: USD_ADDRESS, }, fallbackOracle diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-lp/__setup.spec.ts index 8acdbf33..47285ee0 100644 --- a/test-suites/test-lp/__setup.spec.ts +++ b/test-suites/test-lp/__setup.spec.ts @@ -66,7 +66,7 @@ const deployAllMockTokens = async (deployer: Signer) => { const lpConfigData = getReservesConfigByPool(AavePools.lp); for (const tokenSymbol of Object.keys(TokenContractId)) { - if (tokenSymbol === 'UniWETH') { + if (tokenSymbol === 'LpWETH') { tokens[tokenSymbol] = await deployWETHMocked(); await registerContractInJsonDb('WETH', tokens[tokenSymbol]); continue; @@ -165,25 +165,25 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { REN: mockTokens.REN.address, UNI: mockTokens.UNI.address, ENJ: mockTokens.ENJ.address, - UniDAI: mockTokens.UniDAI.address, - UniUSDC: mockTokens.UniUSDC.address, - UniUSDT: mockTokens.UniUSDT.address, - UniWBTC: mockTokens.UniWBTC.address, - UniWETH: mockTokens.UniWETH.address, - UniDAIWETH: mockTokens.UniDAIWETH.address, - UniWBTCWETH: mockTokens.UniWBTCWETH.address, - UniAAVEWETH: mockTokens.UniAAVEWETH.address, - UniBATWETH: mockTokens.UniBATWETH.address, - UniUSDCDAI: mockTokens.UniUSDCDAI.address, - UniCRVWETH: mockTokens.UniCRVWETH.address, - UniLINKWETH: mockTokens.UniLINKWETH.address, - UniMKRWETH: mockTokens.UniMKRWETH.address, - UniRENWETH: mockTokens.UniRENWETH.address, - UniSNXWETH: mockTokens.UniSNXWETH.address, - UniUNIWETH: mockTokens.UniUNIWETH.address, - UniUSDCWETH: mockTokens.UniUSDCWETH.address, - UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, - UniYFIWETH: mockTokens.UniYFIWETH.address, + LpDAI: mockTokens.LpDAI.address, + LpUSDC: mockTokens.LpUSDC.address, + LpUSDT: mockTokens.LpUSDT.address, + LpWBTC: mockTokens.LpWBTC.address, + LpWETH: mockTokens.LpWETH.address, + LpDAIWETH: mockTokens.LpDAIWETH.address, + LpWBTCWETH: mockTokens.LpWBTCWETH.address, + LpAAVEWETH: mockTokens.LpAAVEWETH.address, + LpBATWETH: mockTokens.LpBATWETH.address, + LpUSDCDAI: mockTokens.LpUSDCDAI.address, + LpCRVWETH: mockTokens.LpCRVWETH.address, + LpLINKWETH: mockTokens.LpLINKWETH.address, + LpMKRWETH: mockTokens.LpMKRWETH.address, + LpRENWETH: mockTokens.LpRENWETH.address, + LpSNXWETH: mockTokens.LpSNXWETH.address, + LpUNIWETH: mockTokens.LpUNIWETH.address, + LpUSDCWETH: mockTokens.LpUSDCWETH.address, + LpWBTCUSDC: mockTokens.LpWBTCUSDC.address, + LpYFIWETH: mockTokens.LpYFIWETH.address, USD: USD_ADDRESS, }, fallbackOracle @@ -268,7 +268,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { await deployWalletBalancerProvider(); - await deployWETHGateway([mockTokens.UniWETH.address, lendingPoolAddress]); + await deployWETHGateway([mockTokens.LpWETH.address, lendingPoolAddress]); console.timeEnd('setup'); }; diff --git a/test-suites/test-lp/atoken-transfer.spec.ts b/test-suites/test-lp/atoken-transfer.spec.ts index 268302e3..7e7c029b 100644 --- a/test-suites/test-lp/atoken-transfer.spec.ts +++ b/test-suites/test-lp/atoken-transfer.spec.ts @@ -33,7 +33,7 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { const name = await aDai.name(); - expect(name).to.be.equal('Aave interest bearing UniDAI'); + expect(name).to.be.equal('Aave interest bearing LpDAI'); const fromBalance = await aDai.balanceOf(users[0].address); const toBalance = await aDai.balanceOf(users[1].address); diff --git a/test-suites/test-lp/helpers/make-suite.ts b/test-suites/test-lp/helpers/make-suite.ts index fd78ae6f..10499ecc 100644 --- a/test-suites/test-lp/helpers/make-suite.ts +++ b/test-suites/test-lp/helpers/make-suite.ts @@ -128,15 +128,15 @@ export async function initializeMakeSuite() { testEnv.helpersContract = await getAaveProtocolDataProvider(); const allTokens = await testEnv.helpersContract.getAllATokens(); - const aDaiAddress = allTokens.find((aToken) => aToken.symbol === 'aUniDAI')?.tokenAddress; + const aDaiAddress = allTokens.find((aToken) => aToken.symbol === 'aLpDAI')?.tokenAddress; - const aWEthAddress = allTokens.find((aToken) => aToken.symbol === 'aUniWETH')?.tokenAddress; + const aWEthAddress = allTokens.find((aToken) => aToken.symbol === 'aLpWETH')?.tokenAddress; const reservesTokens = await testEnv.helpersContract.getAllReservesTokens(); - const daiAddress = reservesTokens.find((token) => token.symbol === 'UniDAI')?.tokenAddress; - const usdcAddress = reservesTokens.find((token) => token.symbol === 'UniUSDC')?.tokenAddress; - const aaveAddress = reservesTokens.find((token) => token.symbol === 'UniAAVEWETH')?.tokenAddress; + const daiAddress = reservesTokens.find((token) => token.symbol === 'LpDAI')?.tokenAddress; + const usdcAddress = reservesTokens.find((token) => token.symbol === 'LpUSDC')?.tokenAddress; + const aaveAddress = reservesTokens.find((token) => token.symbol === 'LpAAVEWETH')?.tokenAddress; const wethAddress = reservesTokens.find((token) => token.symbol === 'WETH')?.tokenAddress; if (!aDaiAddress || !aWEthAddress) { diff --git a/test-suites/test-lp/helpers/scenarios/borrow-negatives.json b/test-suites/test-lp/helpers/scenarios/borrow-negatives.json index 6ab95c87..4ae81f1f 100644 --- a/test-suites/test-lp/helpers/scenarios/borrow-negatives.json +++ b/test-suites/test-lp/helpers/scenarios/borrow-negatives.json @@ -3,12 +3,12 @@ "description": "Test cases for the deposit function.", "stories": [ { - "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 UNIDAI with rate mode NONE (revert expected)", + "description": "User 0 deposits 1000 LPDAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 LPDAI with rate mode NONE (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -60,7 +60,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "none", "user": "1" @@ -71,12 +71,12 @@ ] }, { - "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 UNIDAI with an invalid rate mode (revert expected)", + "description": "User 0 deposits 1000 LPDAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 LPDAI with an invalid rate mode (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -85,7 +85,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -93,7 +93,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -128,7 +128,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "invalid", "user": "1" diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json b/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json index 4f12eb86..00596048 100644 --- a/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json +++ b/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json @@ -3,12 +3,12 @@ "description": "Test cases for the borrow function, stable mode.", "stories": [ { - "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 WETH as collateral and borrows 100 UNIDAI at stable rate", + "description": "User 0 deposits 1000 LPDAI, user 1 deposits 1 WETH as collateral and borrows 100 LPDAI at stable rate", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -61,7 +61,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "stable", "user": "1", @@ -72,12 +72,12 @@ ] }, { - "description": "User 1 tries to borrow the rest of the UNIDAI liquidity (revert expected)", + "description": "User 1 tries to borrow the rest of the LPDAI liquidity (revert expected)", "actions": [ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "900", "borrowRateMode": "stable", "user": "1" @@ -88,13 +88,13 @@ ] }, { - "description": "User 1 repays half of the UNIDAI borrow after one year", + "description": "User 1 repays half of the LPDAI borrow after one year", "actions": [ { "name": "mint", - "description": "Mint 10 UNIDAI to cover the interest", + "description": "Mint 10 LPDAI to cover the interest", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "10", "user": "1" }, @@ -103,7 +103,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1" }, "expected": "success" @@ -111,7 +111,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "50", "user": "1", "onBehalfOf": "1", @@ -122,13 +122,13 @@ ] }, { - "description": "User 1 repays the rest of the UNIDAI borrow after one year", + "description": "User 1 repays the rest of the LPDAI borrow after one year", "actions": [ { "name": "mint", - "description": "Mint 15 UNIDAI to cover the interest", + "description": "Mint 15 LPDAI to cover the interest", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "15", "user": "1" }, @@ -137,7 +137,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1" }, "expected": "success" @@ -145,7 +145,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -156,12 +156,12 @@ ] }, { - "description": "User 0 withdraws the deposited UNIDAI plus interest", + "description": "User 0 withdraws the deposited LPDAI plus interest", "actions": [ { "name": "withdraw", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "0" }, @@ -170,12 +170,12 @@ ] }, { - "description": "User 1 deposits 1000 UNIDAI, user 2 tries to borrow 1000 UNIDAI at a stable rate without any collateral (revert expected) User 1 withdrawws", + "description": "User 1 deposits 1000 LPDAI, user 2 tries to borrow 1000 LPDAI at a stable rate without any collateral (revert expected) User 1 withdrawws", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "1" }, @@ -184,7 +184,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1" }, "expected": "success" @@ -192,7 +192,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "1" }, @@ -201,7 +201,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "borrowRateMode": "stable", "user": "2" @@ -212,7 +212,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "1" }, @@ -221,12 +221,12 @@ ] }, { - "description": "User 0 deposits 1000 UNIDAI, user 1,2,3,4 deposit 1 WETH each and borrow 100 UNIDAI at stable rate. Everything is repaid, user 0 withdraws", + "description": "User 0 deposits 1000 LPDAI, user 1,2,3,4 deposit 1 WETH each and borrow 100 LPDAI at stable rate. Everything is repaid, user 0 withdraws", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -235,7 +235,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -243,7 +243,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -278,7 +278,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "stable", "user": "1", @@ -315,7 +315,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "stable", "user": "2", @@ -352,7 +352,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "stable", "user": "3", @@ -389,7 +389,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "stable", "user": "4", @@ -399,9 +399,9 @@ }, { "name": "mint", - "description": "Mint 15 UNIDAI to cover the interest", + "description": "Mint 15 LPDAI to cover the interest", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "15", "user": "1" }, @@ -410,7 +410,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1" }, "expected": "success" @@ -418,7 +418,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -428,9 +428,9 @@ }, { "name": "mint", - "description": "Mint 20 UNIDAI to cover the interest", + "description": "Mint 20 LPDAI to cover the interest", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "20", "user": "2" }, @@ -439,7 +439,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "2" }, "expected": "success" @@ -447,7 +447,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "2", "onBehalfOf": "2", @@ -457,9 +457,9 @@ }, { "name": "mint", - "description": "Mint 30 UNIDAI to cover the interest", + "description": "Mint 30 LPDAI to cover the interest", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "30", "user": "3" }, @@ -468,7 +468,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "3" }, "expected": "success" @@ -476,7 +476,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "3", "onBehalfOf": "3", @@ -486,9 +486,9 @@ }, { "name": "mint", - "description": "Mint 30 UNIDAI to cover the interest", + "description": "Mint 30 LPDAI to cover the interest", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "30", "user": "4" }, @@ -497,7 +497,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "4" }, "expected": "success" @@ -505,7 +505,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "4", "onBehalfOf": "4", @@ -516,7 +516,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "0" }, @@ -525,12 +525,12 @@ ] }, { - "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 2 WETH and borrow 100 UNIDAI at stable rate first, then 100 UNIDAI at variable rate, repays everything. User 0 withdraws", + "description": "User 0 deposits 1000 LPDAI, user 1 deposits 2 WETH and borrow 100 LPDAI at stable rate first, then 100 LPDAI at variable rate, repays everything. User 0 withdraws", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -539,7 +539,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -547,7 +547,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -582,7 +582,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "stable", "user": "1", @@ -593,7 +593,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "variable", "user": "1", @@ -603,9 +603,9 @@ }, { "name": "mint", - "description": "Mint 50 UNIDAI to cover the interest", + "description": "Mint 50 LPDAI to cover the interest", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "50", "user": "1" }, @@ -614,7 +614,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1" }, "expected": "success" @@ -622,7 +622,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -633,7 +633,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -644,7 +644,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "0" }, diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json b/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json index 482e337c..743ef2e8 100644 --- a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json +++ b/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json @@ -3,12 +3,12 @@ "description": "Test cases for the borrow function, variable mode.", "stories": [ { - "description": "User 2 deposits 1 UNIDAI to account for rounding errors", + "description": "User 2 deposits 1 LPDAI to account for rounding errors", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1", "user": "2" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "2" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1", "user": "2" }, @@ -34,12 +34,12 @@ ] }, { - "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 1 WETH as collateral and borrows 100 UNIDAI at variable rate", + "description": "User 0 deposits 1000 LPDAI, user 1 deposits 1 WETH as collateral and borrows 100 LPDAI at variable rate", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -48,7 +48,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -56,7 +56,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -91,7 +91,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "variable", "user": "1", @@ -102,12 +102,12 @@ ] }, { - "description": "User 1 tries to borrow the rest of the UNIDAI liquidity (revert expected)", + "description": "User 1 tries to borrow the rest of the LPDAI liquidity (revert expected)", "actions": [ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "900", "borrowRateMode": "variable", "user": "1" @@ -118,12 +118,12 @@ ] }, { - "description": "User 1 tries to repay 0 UNIDAI (revert expected)", + "description": "User 1 tries to repay 0 LPDAI (revert expected)", "actions": [ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "0", "user": "1", "onBehalfOf": "1" @@ -134,12 +134,12 @@ ] }, { - "description": "User 1 repays a small amount of UNIDAI, enough to cover a small part of the interest", + "description": "User 1 repays a small amount of LPDAI, enough to cover a small part of the interest", "actions": [ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1" }, "expected": "success" @@ -147,7 +147,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1.25", "user": "1", "onBehalfOf": "1", @@ -158,13 +158,13 @@ ] }, { - "description": "User 1 repays the UNIDAI borrow after one year", + "description": "User 1 repays the LPDAI borrow after one year", "actions": [ { "name": "mint", - "description": "Mint 10 UNIDAI to cover the interest", + "description": "Mint 10 LPDAI to cover the interest", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "10", "user": "1" }, @@ -173,7 +173,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -184,12 +184,12 @@ ] }, { - "description": "User 0 withdraws the deposited UNIDAI plus interest", + "description": "User 0 withdraws the deposited LPDAI plus interest", "actions": [ { "name": "withdraw", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "0" }, @@ -243,7 +243,7 @@ ] }, { - "description": "User 0 deposits 1 WETH, user 1 deposits 100 UNILINKWETH as collateral and borrows 0.5 WETH at variable rate", + "description": "User 0 deposits 1 WETH, user 1 deposits 100 LPLINKWETH as collateral and borrows 0.5 WETH at variable rate", "actions": [ { "name": "mint", @@ -274,7 +274,7 @@ { "name": "mint", "args": { - "reserve": "UNILINKWETH", + "reserve": "LPLINKWETH", "amount": "100", "user": "1" }, @@ -283,7 +283,7 @@ { "name": "approve", "args": { - "reserve": "UNILINKWETH", + "reserve": "LPLINKWETH", "user": "1" }, "expected": "success" @@ -292,7 +292,7 @@ { "name": "deposit", "args": { - "reserve": "UNILINKWETH", + "reserve": "LPLINKWETH", "amount": "100", "user": "1" }, @@ -431,7 +431,7 @@ { "name": "withdraw", "args": { - "reserve": "UNILINKWETH", + "reserve": "LPLINKWETH", "amount": "-1", "user": "1" }, @@ -441,12 +441,12 @@ }, { - "description": "User 2 deposits 1 UNIUSDC to account for rounding errors", + "description": "User 2 deposits 1 LPUSDC to account for rounding errors", "actions": [ { "name": "mint", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1", "user": "2" }, @@ -455,7 +455,7 @@ { "name": "approve", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "2" }, "expected": "success" @@ -463,7 +463,7 @@ { "name": "deposit", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1", "user": "2" }, @@ -472,12 +472,12 @@ ] }, { - "description": "User 0 deposits 1000 UNIUSDC, user 1 deposits 1 WETH as collateral and borrows 100 UNIUSDC at variable rate", + "description": "User 0 deposits 1000 LPUSDC, user 1 deposits 1 WETH as collateral and borrows 100 LPUSDC at variable rate", "actions": [ { "name": "mint", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "0" }, @@ -486,7 +486,7 @@ { "name": "approve", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "0" }, "expected": "success" @@ -494,7 +494,7 @@ { "name": "deposit", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "0" }, @@ -529,7 +529,7 @@ { "name": "borrow", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "100", "borrowRateMode": "variable", "user": "1", @@ -540,12 +540,12 @@ ] }, { - "description": "User 1 tries to borrow the rest of the UNIUSDC liquidity (revert expected)", + "description": "User 1 tries to borrow the rest of the LPUSDC liquidity (revert expected)", "actions": [ { "name": "borrow", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "900", "borrowRateMode": "variable", "user": "1" @@ -556,13 +556,13 @@ ] }, { - "description": "User 1 repays the UNIUSDC borrow after one year", + "description": "User 1 repays the LPUSDC borrow after one year", "actions": [ { "name": "mint", - "description": "Mint 10 UNIUSDC to cover the interest", + "description": "Mint 10 LPUSDC to cover the interest", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "10", "user": "1" }, @@ -571,7 +571,7 @@ { "name": "approve", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "1" }, "expected": "success" @@ -579,7 +579,7 @@ { "name": "repay", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -590,12 +590,12 @@ ] }, { - "description": "User 0 withdraws the deposited UNIUSDC plus interest", + "description": "User 0 withdraws the deposited LPUSDC plus interest", "actions": [ { "name": "withdraw", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "-1", "user": "0" }, @@ -618,12 +618,12 @@ ] }, { - "description": "User 1 deposits 1000 UNIDAI, user 3 tries to borrow 1000 UNIDAI without any collateral (revert expected)", + "description": "User 1 deposits 1000 LPDAI, user 3 tries to borrow 1000 LPDAI without any collateral (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "1" }, @@ -632,7 +632,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1" }, "expected": "success" @@ -640,7 +640,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "1" }, @@ -649,7 +649,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "borrowRateMode": "variable", "user": "3" @@ -660,7 +660,7 @@ ] }, { - "description": "user 3 deposits 0.1 WETH collateral to borrow 100 UNIDAI; 0.1 WETH is not enough to borrow 100 UNIDAI (revert expected)", + "description": "user 3 deposits 0.1 WETH collateral to borrow 100 LPDAI; 0.1 WETH is not enough to borrow 100 LPDAI (revert expected)", "actions": [ { "name": "mint", @@ -691,7 +691,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "variable", "user": "3" @@ -716,12 +716,12 @@ ] }, { - "description": "User 1 deposits 1000 UNIUSDC, user 3 tries to borrow 1000 UNIUSDC without any collateral (revert expected)", + "description": "User 1 deposits 1000 LPUSDC, user 3 tries to borrow 1000 LPUSDC without any collateral (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "1" }, @@ -730,7 +730,7 @@ { "name": "approve", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "1" }, "expected": "success" @@ -738,7 +738,7 @@ { "name": "deposit", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "1" }, @@ -747,7 +747,7 @@ { "name": "borrow", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "borrowRateMode": "variable", "user": "3" @@ -758,7 +758,7 @@ ] }, { - "description": "user 3 deposits 0.1 WETH collateral to borrow 100 UNIUSDC; 0.1 WETH is not enough to borrow 100 UNIUSDC (revert expected)", + "description": "user 3 deposits 0.1 WETH collateral to borrow 100 LPUSDC; 0.1 WETH is not enough to borrow 100 LPUSDC (revert expected)", "actions": [ { "name": "mint", @@ -789,7 +789,7 @@ { "name": "borrow", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "100", "borrowRateMode": "variable", "user": "3" @@ -814,12 +814,12 @@ ] }, { - "description": "User 0 deposits 1000 UNIDAI, user 6 deposits 2 WETH and borrow 100 UNIDAI at variable rate first, then 100 UNIDAI at stable rate, repays everything. User 0 withdraws", + "description": "User 0 deposits 1000 LPDAI, user 6 deposits 2 WETH and borrow 100 LPDAI at variable rate first, then 100 LPDAI at stable rate, repays everything. User 0 withdraws", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -828,7 +828,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -836,7 +836,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -871,7 +871,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "variable", "user": "6", @@ -882,7 +882,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "stable", "user": "6", @@ -892,9 +892,9 @@ }, { "name": "mint", - "description": "Mint 50 UNIDAI to cover the interest", + "description": "Mint 50 LPDAI to cover the interest", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "50", "user": "6" }, @@ -903,7 +903,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "6" }, "expected": "success" @@ -911,7 +911,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "6", "onBehalfOf": "6", @@ -922,7 +922,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "6", "onBehalfOf": "6", @@ -933,7 +933,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "0" }, diff --git a/test-suites/test-lp/helpers/scenarios/credit-delegation.json b/test-suites/test-lp/helpers/scenarios/credit-delegation.json index 6b9ece7e..cb8e82d6 100644 --- a/test-suites/test-lp/helpers/scenarios/credit-delegation.json +++ b/test-suites/test-lp/helpers/scenarios/credit-delegation.json @@ -3,7 +3,7 @@ "description": "Test cases for the credit delegation related functions.", "stories": [ { - "description": "User 3 deposits 1000 WETH. User 0 deposits 1000 UNIDAI, user 0 delegates borrowing of 1 WETH on variable to user 4, user 4 borrows 1 WETH variable on behalf of user 0", + "description": "User 3 deposits 1000 WETH. User 0 deposits 1000 LPDAI, user 0 delegates borrowing of 1 WETH on variable to user 4, user 4 borrows 1 WETH variable on behalf of user 0", "actions": [ { "name": "mint", @@ -34,7 +34,7 @@ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -43,7 +43,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -51,7 +51,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, diff --git a/test-suites/test-lp/helpers/scenarios/deposit.json b/test-suites/test-lp/helpers/scenarios/deposit.json index 385518b8..960011e3 100644 --- a/test-suites/test-lp/helpers/scenarios/deposit.json +++ b/test-suites/test-lp/helpers/scenarios/deposit.json @@ -3,12 +3,12 @@ "description": "Test cases for the deposit function.", "stories": [ { - "description": "User 0 Deposits 1000 UNIDAI in an empty reserve", + "description": "User 0 Deposits 1000 LPDAI in an empty reserve", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -34,12 +34,12 @@ ] }, { - "description": "User 1 deposits 1000 UNIDAI after user 0", + "description": "User 1 deposits 1000 LPDAI after user 0", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "1" }, @@ -48,7 +48,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1" }, "expected": "success" @@ -56,7 +56,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "1" }, @@ -65,12 +65,12 @@ ] }, { - "description": "User 0 deposits 1000 UNIUSDC in an empty reserve", + "description": "User 0 deposits 1000 LPUSDC in an empty reserve", "actions": [ { "name": "mint", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "0" }, @@ -79,7 +79,7 @@ { "name": "approve", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "0" }, "expected": "success" @@ -87,7 +87,7 @@ { "name": "deposit", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "0" }, @@ -96,12 +96,12 @@ ] }, { - "description": "User 1 deposits 1000 UNIUSDC after user 0", + "description": "User 1 deposits 1000 LPUSDC after user 0", "actions": [ { "name": "mint", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "1" }, @@ -110,7 +110,7 @@ { "name": "approve", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "1" }, "expected": "success" @@ -118,7 +118,7 @@ { "name": "deposit", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "1" }, @@ -214,12 +214,12 @@ ] }, { - "description": "User 1 deposits 0 UNIDAI", + "description": "User 1 deposits 0 LPDAI", "actions": [ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "0", "user": "1" }, @@ -229,12 +229,12 @@ ] }, { - "description": "User 1 deposits 100 UNIDAI on behalf of user 2, user 2 tries to borrow 0.1 WETH", + "description": "User 1 deposits 100 LPDAI on behalf of user 2, user 2 tries to borrow 0.1 WETH", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "user": "1" }, @@ -243,7 +243,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "user": "1", "onBehalfOf": "2" diff --git a/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json b/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json index 32c7c9bb..6c9325ef 100644 --- a/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json +++ b/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json @@ -8,7 +8,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "0", "target": "1" }, @@ -18,12 +18,12 @@ ] }, { - "description": "User 0 deposits 1000 UNIUSDC, user 1 deposits 7 WETH, borrows 250 UNIUSDC at a stable rate, user 0 rebalances user 1 (revert expected)", + "description": "User 0 deposits 1000 LPUSDC, user 1 deposits 7 WETH, borrows 250 LPUSDC at a stable rate, user 0 rebalances user 1 (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "0" }, @@ -32,7 +32,7 @@ { "name": "approve", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "0" }, "expected": "success" @@ -40,7 +40,7 @@ { "name": "deposit", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "0" }, @@ -75,7 +75,7 @@ { "name": "borrow", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "250", "borrowRateMode": "stable", "user": "1" @@ -85,7 +85,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "0", "target": "1" }, @@ -100,7 +100,7 @@ { "name": "borrow", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "200", "borrowRateMode": "variable", "user": "1" @@ -110,7 +110,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "0", "target": "1" }, @@ -125,7 +125,7 @@ { "name": "borrow", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "200", "borrowRateMode": "variable", "user": "1" @@ -135,7 +135,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "0", "target": "1" }, @@ -150,7 +150,7 @@ { "name": "borrow", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "280", "borrowRateMode": "variable", "user": "1" @@ -160,7 +160,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "0", "target": "1" }, @@ -171,12 +171,12 @@ }, { - "description": "User 1 borrows the remaining UNIUSDC (usage ratio = 100%) at variable. User 0 rebalances user 1", + "description": "User 1 borrows the remaining LPUSDC (usage ratio = 100%) at variable. User 0 rebalances user 1", "actions": [ { "name": "borrow", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "20", "borrowRateMode": "variable", "user": "1" @@ -186,7 +186,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "0", "target": "1" }, diff --git a/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json b/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json index 71a3f860..b0cee5ee 100644 --- a/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json +++ b/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json @@ -3,12 +3,12 @@ "description": "Test cases for the setUserUseReserveAsCollateral() function.", "stories": [ { - "description": "User 0 Deposits 1000 UNIDAI, disables UNIDAI as collateral", + "description": "User 0 Deposits 1000 LPDAI, disables LPDAI as collateral", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -34,7 +34,7 @@ { "name": "setUseAsCollateral", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0", "useAsCollateral": "false" }, @@ -43,7 +43,7 @@ ] }, { - "description": "User 1 Deposits 2 WETH, disables WETH as collateral, borrows 400 UNIDAI (revert expected)", + "description": "User 1 Deposits 2 WETH, disables WETH as collateral, borrows 400 LPDAI (revert expected)", "actions": [ { "name": "mint", @@ -83,7 +83,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "400", "borrowRateMode": "variable", "user": "1" @@ -94,7 +94,7 @@ ] }, { - "description": "User 1 enables WETH as collateral, borrows 400 UNIDAI", + "description": "User 1 enables WETH as collateral, borrows 400 LPDAI", "actions": [ { "name": "setUseAsCollateral", @@ -108,7 +108,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "400", "borrowRateMode": "variable", "user": "1" @@ -133,12 +133,12 @@ ] }, { - "description": "User 1 Deposits 10 UNILINKWETH, disables WETH as collateral. Should revert as 10 UNILINKWETH are not enough to cover the debt (revert expected)", + "description": "User 1 Deposits 10 LPLINKWETH, disables WETH as collateral. Should revert as 10 LPLINKWETH are not enough to cover the debt (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "UNILINKWETH", + "reserve": "LPLINKWETH", "amount": "10", "user": "1" }, @@ -147,7 +147,7 @@ { "name": "approve", "args": { - "reserve": "UNILINKWETH", + "reserve": "LPLINKWETH", "user": "1" }, "expected": "success" @@ -155,7 +155,7 @@ { "name": "deposit", "args": { - "reserve": "UNILINKWETH", + "reserve": "LPLINKWETH", "amount": "10", "user": "1" }, @@ -173,12 +173,12 @@ ] }, { - "description": "User 1 Deposits 640 more UNILINKWETH (enough to cover the UNIDAI debt), disables WETH as collateral", + "description": "User 1 Deposits 640 more LPLINKWETH (enough to cover the LPDAI debt), disables WETH as collateral", "actions": [ { "name": "mint", "args": { - "reserve": "UNILINKWETH", + "reserve": "LPLINKWETH", "amount": "640", "user": "1" }, @@ -187,7 +187,7 @@ { "name": "deposit", "args": { - "reserve": "UNILINKWETH", + "reserve": "LPLINKWETH", "amount": "640", "user": "1" }, @@ -205,12 +205,12 @@ ] }, { - "description": "User 1 disables UNILINKWETH as collateral (revert expected)", + "description": "User 1 disables LPLINKWETH as collateral (revert expected)", "actions": [ { "name": "setUseAsCollateral", "args": { - "reserve": "UNILINKWETH", + "reserve": "LPLINKWETH", "user": "1", "useAsCollateral": "false" }, diff --git a/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json b/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json index dcd7ac98..98011e48 100644 --- a/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json +++ b/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json @@ -8,7 +8,7 @@ { "name": "swapBorrowRateMode", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1", "borrowRateMode": "variable" }, @@ -23,7 +23,7 @@ { "name": "swapBorrowRateMode", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1", "borrowRateMode": "stable" }, @@ -33,12 +33,12 @@ ] }, { - "description": "User 0 deposits 1000 UNIDAI, user 1 deposits 2 WETH as collateral, borrows 100 UNIDAI at variable rate and swaps to stable after one year", + "description": "User 0 deposits 1000 LPDAI, user 1 deposits 2 WETH as collateral, borrows 100 LPDAI at variable rate and swaps to stable after one year", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -47,7 +47,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -55,7 +55,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -90,7 +90,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "variable", "user": "1", @@ -101,7 +101,7 @@ { "name": "swapBorrowRateMode", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1", "borrowRateMode": "variable" }, @@ -110,12 +110,12 @@ ] }, { - "description": "User 1 borrows another 100 UNIDAI, and swaps back to variable after one year, repays the loan", + "description": "User 1 borrows another 100 LPDAI, and swaps back to variable after one year, repays the loan", "actions": [ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "borrowRateMode": "stable", "user": "1", @@ -126,7 +126,7 @@ { "name": "swapBorrowRateMode", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1", "borrowRateMode": "stable" }, @@ -134,9 +134,9 @@ }, { "name": "mint", - "description": "Mint 50 UNIDAI to cover the interest", + "description": "Mint 50 LPDAI to cover the interest", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "50", "user": "1" }, @@ -145,7 +145,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1" }, "expected": "success" @@ -153,7 +153,7 @@ { "name": "repay", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "1", "onBehalfOf": "1", diff --git a/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json b/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json index 209a7de8..1d7ba442 100644 --- a/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json +++ b/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json @@ -3,12 +3,12 @@ "description": "Redeem function.", "stories": [ { - "description": "Users 0 Deposits 1000 UNIDAI and tries to redeem 0 UNIDAI (revert expected)", + "description": "Users 0 Deposits 1000 LPDAI and tries to redeem 0 LPDAI (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -35,7 +35,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "0", "user": "0" }, @@ -45,12 +45,12 @@ ] }, { - "description": "Users 0 tries to redeem 1100 UNIDAI from the 1000 UNIDAI deposited (revert expected)", + "description": "Users 0 tries to redeem 1100 LPDAI from the 1000 LPDAI deposited (revert expected)", "actions": [ { "name": "withdraw", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1100", "user": "0" }, @@ -60,7 +60,7 @@ ] }, { - "description": "Users 1 deposits 1 WETH, borrows 100 UNIDAI, tries to redeem the 1 WETH deposited (revert expected)", + "description": "Users 1 deposits 1 WETH, borrows 100 LPDAI, tries to redeem the 1 WETH deposited (revert expected)", "actions": [ { "name": "mint", @@ -91,7 +91,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "user": "1", "borrowRateMode": "stable" diff --git a/test-suites/test-lp/helpers/scenarios/withdraw.json b/test-suites/test-lp/helpers/scenarios/withdraw.json index ed0d2ff7..78ec38ca 100644 --- a/test-suites/test-lp/helpers/scenarios/withdraw.json +++ b/test-suites/test-lp/helpers/scenarios/withdraw.json @@ -3,12 +3,12 @@ "description": "withdraw function.", "stories": [ { - "description": "User 0 Deposits 1000 UNIDAI in an empty reserve", + "description": "User 0 Deposits 1000 LPDAI in an empty reserve", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "0" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -34,12 +34,12 @@ ] }, { - "description": "User 0 withdraws half of the deposited UNIDAI", + "description": "User 0 withdraws half of the deposited LPDAI", "actions": [ { "name": "withdraw", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "500", "user": "0" }, @@ -48,12 +48,12 @@ ] }, { - "description": "User 0 withdraws remaining half of the deposited UNIDAI", + "description": "User 0 withdraws remaining half of the deposited LPDAI", "actions": [ { "name": "withdraw", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "0" }, @@ -62,12 +62,12 @@ ] }, { - "description": "User 0 Deposits 1000 UNIUSDC in an empty reserve", + "description": "User 0 Deposits 1000 LPUSDC in an empty reserve", "actions": [ { "name": "mint", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "0" }, @@ -76,7 +76,7 @@ { "name": "approve", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "0" }, "expected": "success" @@ -84,7 +84,7 @@ { "name": "deposit", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "0" }, @@ -93,12 +93,12 @@ ] }, { - "description": "User 0 withdraws half of the deposited UNIUSDC", + "description": "User 0 withdraws half of the deposited LPUSDC", "actions": [ { "name": "withdraw", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "500", "user": "0" }, @@ -107,12 +107,12 @@ ] }, { - "description": "User 0 withdraws remaining half of the deposited UNIUSDC", + "description": "User 0 withdraws remaining half of the deposited LPUSDC", "actions": [ { "name": "withdraw", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "-1", "user": "0" }, @@ -180,12 +180,12 @@ ] }, { - "description": "Users 0 and 1 Deposit 1000 UNIDAI, both withdraw", + "description": "Users 0 and 1 Deposit 1000 LPDAI, both withdraw", "actions": [ { "name": "mint", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "1" }, @@ -194,7 +194,7 @@ { "name": "approve", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "user": "1" }, "expected": "success" @@ -202,7 +202,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -211,7 +211,7 @@ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "1" }, @@ -220,7 +220,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "0" }, @@ -229,7 +229,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "-1", "user": "1" }, @@ -238,12 +238,12 @@ ] }, { - "description": "Users 0 deposits 1000 UNIDAI, user 1 Deposit 1000 UNIUSDC and 1 WETH, borrows 100 UNIDAI. User 1 tries to withdraw all the UNIUSDC", + "description": "Users 0 deposits 1000 LPDAI, user 1 Deposit 1000 LPUSDC and 1 WETH, borrows 100 LPDAI. User 1 tries to withdraw all the LPUSDC", "actions": [ { "name": "deposit", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "1000", "user": "0" }, @@ -252,7 +252,7 @@ { "name": "mint", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "1" }, @@ -261,7 +261,7 @@ { "name": "approve", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "user": "1" }, "expected": "success" @@ -269,7 +269,7 @@ { "name": "deposit", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "1000", "user": "1" }, @@ -304,7 +304,7 @@ { "name": "borrow", "args": { - "reserve": "UNIDAI", + "reserve": "LPDAI", "amount": "100", "user": "1", "borrowRateMode": "stable" @@ -314,7 +314,7 @@ { "name": "withdraw", "args": { - "reserve": "UNIUSDC", + "reserve": "LPUSDC", "amount": "-1", "user": "1" }, diff --git a/test-suites/test-lp/helpers/utils/calculations.ts b/test-suites/test-lp/helpers/utils/calculations.ts index f36c0c6a..317645f2 100644 --- a/test-suites/test-lp/helpers/utils/calculations.ts +++ b/test-suites/test-lp/helpers/utils/calculations.ts @@ -1237,9 +1237,9 @@ export const calcExpectedInterestRates = ( ): BigNumber[] => { const { reservesParams } = configuration; - // Fixes WETH - UniWETH mock token symbol mismatch + // Fixes WETH - LpWETH mock token symbol mismatch if(reserveSymbol === 'WETH') { - reserveSymbol = 'UniWETH'; + reserveSymbol = 'LpWETH'; } const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol); const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[ diff --git a/test-suites/test-lp/stable-token.spec.ts b/test-suites/test-lp/stable-token.spec.ts index 9974c5e2..58884018 100644 --- a/test-suites/test-lp/stable-token.spec.ts +++ b/test-suites/test-lp/stable-token.spec.ts @@ -29,7 +29,7 @@ makeSuite('Stable debt token tests', (testEnv: TestEnv) => { const name = await stableDebtContract.name(); - expect(name).to.be.equal('Aave stable debt bearing UniDAI'); + expect(name).to.be.equal('Aave stable debt bearing LpDAI'); await expect(stableDebtContract.burn(deployer.address, '1')).to.be.revertedWith( CT_CALLER_MUST_BE_LENDING_POOL ); diff --git a/test-suites/test-lp/upgradeability.spec.ts b/test-suites/test-lp/upgradeability.spec.ts index 771ae6ed..53050b48 100644 --- a/test-suites/test-lp/upgradeability.spec.ts +++ b/test-suites/test-lp/upgradeability.spec.ts @@ -32,7 +32,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { dai.address, ZERO_ADDRESS, ZERO_ADDRESS, - 'Aave Interest bearing UniDAI updated', + 'Aave Interest bearing LpDAI updated', 'aUniDAI', ]); @@ -40,7 +40,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { pool.address, dai.address, ZERO_ADDRESS, - 'Aave stable debt bearing UniDAI updated', + 'Aave stable debt bearing LpDAI updated', 'stableDebtUniDAI', ]); @@ -48,7 +48,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { pool.address, dai.address, ZERO_ADDRESS, - 'Aave variable debt bearing UniDAI updated', + 'Aave variable debt bearing LpDAI updated', 'variableDebtUniDAI', ]); @@ -108,7 +108,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { const tokenName = await aDai.name(); - expect(tokenName).to.be.eq('Aave Interest bearing UniDAI updated', 'Invalid token name'); + expect(tokenName).to.be.eq('Aave Interest bearing LpDAI updated', 'Invalid token name'); }); it('Tries to update the DAI Stable debt token implementation with a different address than the lendingPoolManager', async () => { @@ -168,7 +168,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { const tokenName = await debtToken.name(); - expect(tokenName).to.be.eq('Aave stable debt bearing UniDAI updated', 'Invalid token name'); + expect(tokenName).to.be.eq('Aave stable debt bearing LpDAI updated', 'Invalid token name'); }); it('Tries to update the DAI variable debt token implementation with a different address than the lendingPoolManager', async () => { @@ -229,6 +229,6 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { const tokenName = await debtToken.name(); - expect(tokenName).to.be.eq('Aave variable debt bearing UniDAI updated', 'Invalid token name'); + expect(tokenName).to.be.eq('Aave variable debt bearing LpDAI updated', 'Invalid token name'); }); }); diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index c59ca92a..c9be6515 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -165,25 +165,25 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { REN: mockTokens.REN.address, UNI: mockTokens.UNI.address, ENJ: mockTokens.ENJ.address, - UniDAI: mockTokens.UniDAI.address, - UniUSDC: mockTokens.UniUSDC.address, - UniUSDT: mockTokens.UniUSDT.address, - UniWBTC: mockTokens.UniWBTC.address, - UniWETH: mockTokens.UniWETH.address, - UniDAIWETH: mockTokens.UniDAIWETH.address, - UniWBTCWETH: mockTokens.UniWBTCWETH.address, - UniAAVEWETH: mockTokens.UniAAVEWETH.address, - UniBATWETH: mockTokens.UniBATWETH.address, - UniUSDCDAI: mockTokens.UniUSDCDAI.address, - UniCRVWETH: mockTokens.UniCRVWETH.address, - UniLINKWETH: mockTokens.UniLINKWETH.address, - UniMKRWETH: mockTokens.UniMKRWETH.address, - UniRENWETH: mockTokens.UniRENWETH.address, - UniSNXWETH: mockTokens.UniSNXWETH.address, - UniUNIWETH: mockTokens.UniUNIWETH.address, - UniUSDCWETH: mockTokens.UniUSDCWETH.address, - UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, - UniYFIWETH: mockTokens.UniYFIWETH.address, + LpDAI: mockTokens.LpDAI.address, + LpUSDC: mockTokens.LpUSDC.address, + LpUSDT: mockTokens.LpUSDT.address, + LpWBTC: mockTokens.LpWBTC.address, + LpWETH: mockTokens.LpWETH.address, + LpDAIWETH: mockTokens.LpDAIWETH.address, + LpWBTCWETH: mockTokens.LpWBTCWETH.address, + LpAAVEWETH: mockTokens.LpAAVEWETH.address, + LpBATWETH: mockTokens.LpBATWETH.address, + LpUSDCDAI: mockTokens.LpUSDCDAI.address, + LpCRVWETH: mockTokens.LpCRVWETH.address, + LpLINKWETH: mockTokens.LpLINKWETH.address, + LpMKRWETH: mockTokens.LpMKRWETH.address, + LpRENWETH: mockTokens.LpRENWETH.address, + LpSNXWETH: mockTokens.LpSNXWETH.address, + LpUNIWETH: mockTokens.LpUNIWETH.address, + LpUSDCWETH: mockTokens.LpUSDCWETH.address, + LpWBTCUSDC: mockTokens.LpWBTCUSDC.address, + LpYFIWETH: mockTokens.LpYFIWETH.address, USD: USD_ADDRESS, }, fallbackOracle From 6fbed47205fd312c72f7437d7393d1d69d200846 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 8 Feb 2021 16:18:49 -0500 Subject: [PATCH 083/219] Fixed deploy-new-asset script --- helpers/contracts-deployments.ts | 4 ++-- tasks/helpers/deploy-new-asset.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index a2b9b826..d6133108 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -300,7 +300,7 @@ export const deployDefaultReserveInterestRateStrategy = async ( ); export const deployStableDebtToken = async ( - args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], + args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], verify: boolean ) => { const instance = await withSaveAndVerify( @@ -324,7 +324,7 @@ export const deployStableDebtToken = async ( export const deployVariableDebtToken = async ( - args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], + args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], verify: boolean ) => { const instance = await withSaveAndVerify( diff --git a/tasks/helpers/deploy-new-asset.ts b/tasks/helpers/deploy-new-asset.ts index 912ebff1..50cde45b 100644 --- a/tasks/helpers/deploy-new-asset.ts +++ b/tasks/helpers/deploy-new-asset.ts @@ -53,9 +53,9 @@ WRONG RESERVE ASSET SETUP: poolAddress, reserveAssetAddress, treasuryAddress, + ZERO_ADDRESS, // Incentives Controller `Aave interest bearing ${symbol}`, `a${symbol}`, - ZERO_ADDRESS, ], verify ); @@ -63,9 +63,9 @@ WRONG RESERVE ASSET SETUP: [ poolAddress, reserveAssetAddress, + ZERO_ADDRESS, // Incentives Controller `Aave stable debt bearing ${symbol}`, `stableDebt${symbol}`, - ZERO_ADDRESS, ], verify ); @@ -73,9 +73,9 @@ WRONG RESERVE ASSET SETUP: [ poolAddress, reserveAssetAddress, + ZERO_ADDRESS, // Incentives Controller `Aave variable debt bearing ${symbol}`, `variableDebt${symbol}`, - ZERO_ADDRESS, ], verify ); From deb99b6e06fd531ed4c2e2a04673de25da648453 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 8 Feb 2021 17:27:02 -0500 Subject: [PATCH 084/219] Updated reserve parameters to fit risk params --- markets/lp/reservesConfigs.ts | 44 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/markets/lp/reservesConfigs.ts b/markets/lp/reservesConfigs.ts index d82680cb..9b78d748 100644 --- a/markets/lp/reservesConfigs.ts +++ b/markets/lp/reservesConfigs.ts @@ -13,7 +13,7 @@ export const strategyWETH: IReserveParams = { liquidationThreshold: '8250', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -25,12 +25,12 @@ export const strategyWBTC: IReserveParams = { 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(3).multipliedBy(oneRay).toFixed(), + stableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(), baseLTVAsCollateral: '7000', liquidationThreshold: '7500', liquidationBonus: '11000', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '8', aTokenImpl: eContractid.AToken, reserveFactor: '2000' @@ -47,7 +47,7 @@ export const strategyDAI: IReserveParams = { liquidationThreshold: '8000', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -57,14 +57,14 @@ export const strategyUSDC: IReserveParams = { 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.60).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(), stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(), stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(), baseLTVAsCollateral: '8000', liquidationThreshold: '8500', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '6', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -81,7 +81,7 @@ export const strategyUSDT: IReserveParams = { liquidationThreshold: '8500', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '6', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -98,10 +98,10 @@ export const strategyDAIWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '500' + reserveFactor: '1000' }; export const strategyWBTCWETH: IReserveParams = { @@ -115,7 +115,7 @@ export const strategyWBTCWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -132,7 +132,7 @@ export const strategyAAVEWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '500' @@ -149,7 +149,7 @@ export const strategyBATWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -166,7 +166,7 @@ export const strategyUSDCDAI: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -183,7 +183,7 @@ export const strategyCRVWETH: IReserveParams = { liquidationThreshold: '6000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '500' @@ -200,7 +200,7 @@ export const strategyLINKWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -217,7 +217,7 @@ export const strategyMKRWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -234,7 +234,7 @@ export const strategyRENWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -251,7 +251,7 @@ export const strategySNXWETH: IReserveParams = { liquidationThreshold: '6000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000' @@ -268,7 +268,7 @@ export const strategyUNIWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -285,7 +285,7 @@ export const strategyUSDCWETH: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000' @@ -302,7 +302,7 @@ export const strategyWBTCUSDC: IReserveParams = { liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' @@ -319,7 +319,7 @@ export const strategyYFIWETH: IReserveParams = { liquidationThreshold: '6000', liquidationBonus: '11500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' From 8f68b3b44476f0525576ca99ab4d27ff152e6db9 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 8 Feb 2021 17:42:43 -0500 Subject: [PATCH 085/219] Updated package.json task name --- package.json | 4 ++-- tasks/migrations/{uniswap.mainnet.ts => lp.mainnet.ts} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename tasks/migrations/{uniswap.mainnet.ts => lp.mainnet.ts} (100%) diff --git a/package.json b/package.json index 4e5803c6..57f236fc 100644 --- a/package.json +++ b/package.json @@ -39,12 +39,12 @@ "aave:evm:dev:migration": "npm run compile && hardhat aave:dev", "aave:docker:full:migration": "npm run compile && npm run hardhat:docker -- aave:mainnet", "aave:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- aave:mainnet --verify", - "uniswap:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- uniswap:mainnet --verify", + "lp:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- uniswap:mainnet --verify", "aave:kovan:full:initialize": "npm run hardhat:kovan -- full:initialize-lending-pool --verify --pool Aave", "aave:ropsten:full:migration": "npm run compile && npm run hardhat:ropsten -- aave:mainnet --verify", "aave:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- aave:mainnet", "aave:fork:main": "npm run compile && MAINNET_FORK=true hardhat aave:mainnet", - "uniswap:fork:main": "npm run compile && MAINNET_FORK=true hardhat uniswap:mainnet", + "lp:fork:main": "npm run compile && MAINNET_FORK=true hardhat uniswap:mainnet", "aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify", "aave:main:full:initialize": "npm run compile && MAINNET_FORK=true full:initialize-tokens --pool Aave", "prettier:check": "npx prettier -c 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test-suites/test-aave/**/*.ts'", diff --git a/tasks/migrations/uniswap.mainnet.ts b/tasks/migrations/lp.mainnet.ts similarity index 100% rename from tasks/migrations/uniswap.mainnet.ts rename to tasks/migrations/lp.mainnet.ts From 94cdefb2e93004c8fd3f9ec3a67c7822623bc202 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 8 Feb 2021 23:50:12 -0500 Subject: [PATCH 086/219] Began implementing lp market specific tests --- test-suites/test-lp/atoken-transfer.spec.ts | 6 +- test-suites/test-lp/configurator.spec.ts | 26 ++++ test-suites/test-lp/flashloan.spec.ts | 134 ++++++++++++++++-- .../test-lp/liquidation-atoken.spec.ts | 10 +- .../test-lp/liquidation-underlying.spec.ts | 20 +-- 5 files changed, 167 insertions(+), 29 deletions(-) diff --git a/test-suites/test-lp/atoken-transfer.spec.ts b/test-suites/test-lp/atoken-transfer.spec.ts index 7e7c029b..df58bbcf 100644 --- a/test-suites/test-lp/atoken-transfer.spec.ts +++ b/test-suites/test-lp/atoken-transfer.spec.ts @@ -45,7 +45,7 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { ); }); - it('User 0 deposits 1 WETH and user 1 tries to borrow the WETH with the received DAI as collateral', async () => { + it('User 0 deposits 1 WETH and user 1 tries to borrow the WETH variable with the received DAI as collateral', async () => { const { users, pool, weth, helpersContract } = testEnv; const userAddress = await pool.signer.getAddress(); @@ -61,7 +61,7 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { .borrow( weth.address, ethers.utils.parseEther('0.1'), - RateMode.Stable, + RateMode.Variable, AAVE_REFERRAL, users[1].address ); @@ -71,7 +71,7 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { users[1].address ); - expect(userReserveData.currentStableDebt.toString()).to.be.eq(ethers.utils.parseEther('0.1')); + expect(userReserveData.currentVariableDebt.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 () => { diff --git a/test-suites/test-lp/configurator.spec.ts b/test-suites/test-lp/configurator.spec.ts index 6483b391..f4557791 100644 --- a/test-suites/test-lp/configurator.spec.ts +++ b/test-suites/test-lp/configurator.spec.ts @@ -316,6 +316,32 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); }); + it('Disable stable borrow rate to return to the original state on the ETH reserve', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.disableReserveStableRate(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + }); + it('Check the onlyAaveAdmin on disableReserveStableRate', async () => { const { configurator, users, weth } = testEnv; await expect( diff --git a/test-suites/test-lp/flashloan.spec.ts b/test-suites/test-lp/flashloan.spec.ts index 4a5f5576..22e9ade2 100644 --- a/test-suites/test-lp/flashloan.spec.ts +++ b/test-suites/test-lp/flashloan.spec.ts @@ -22,6 +22,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { VL_COLLATERAL_BALANCE_IS_0, TRANSFER_AMOUNT_EXCEEDS_BALANCE, LP_INVALID_FLASHLOAN_MODE, + VL_STABLE_BORROWING_NOT_ENABLED, SAFEERC20_LOWLEVEL_CALL, LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN, LP_BORROW_ALLOWANCE_NOT_ENOUGH, @@ -384,7 +385,39 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); }); - it('Caller takes a WETH flashloan with mode = 1', async () => { + it('Caller takes a WETH flashloan with mode = 1, should revert since stable borrowing is disabled', async () => { + const { dai, pool, weth, users, helpersContract } = testEnv; + + const caller = users[3]; + + const flashAmount = ethers.utils.parseEther('0.8'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + await expect(pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [flashAmount], + [1], + caller.address, + '0x10', + '0' + )).to.be.revertedWith(VL_STABLE_BORROWING_NOT_ENABLED); + + const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const wethDebtToken = await getStableDebtToken(stableDebtTokenAddress); + + const callerDebt = await wethDebtToken.balanceOf(caller.address); + + expect(callerDebt.toString()).to.be.equal('0', 'Invalid user debt'); + }); + + it('Caller takes a WETH flashloan with mode = 2', async () => { const { dai, pool, weth, users, helpersContract } = testEnv; const caller = users[3]; @@ -399,24 +432,24 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [flashAmount], - [1], + [2], caller.address, '0x10', '0' ); - const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address ); - const wethDebtToken = await getStableDebtToken(stableDebtTokenAddress); + const wethDebtToken = await getStableDebtToken(variableDebtTokenAddress); const callerDebt = await wethDebtToken.balanceOf(caller.address); - expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt'); + expect(callerDebt.toString()).to.be.equal(ethers.utils.parseEther('0.8'), 'Invalid user debt'); }); - it('Caller takes a WETH flashloan with mode = 1 onBehalfOf user without allowance', async () => { + it('Caller takes a WETH flashloan with mode = 1 onBehalfOf user without allowance, should revert since stable borrowing is disabled', async () => { const { dai, pool, weth, users, helpersContract } = testEnv; const caller = users[5]; @@ -449,10 +482,46 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { '0x10', '0' ) + ).to.be.revertedWith(VL_STABLE_BORROWING_NOT_ENABLED); + }); + + it('Caller takes a WETH flashloan with mode = 2 onBehalfOf user without allowance, should revert since allowance is 0', 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], + [2], + onBehalfOf.address, + '0x10', + '0' + ) ).to.be.revertedWith(LP_BORROW_ALLOWANCE_NOT_ENOUGH); }); - it('Caller takes a WETH flashloan with mode = 1 onBehalfOf user with allowance. A loan for onBehalfOf is creatd.', async () => { + it('Caller takes a WETH flashloan with mode = 1 onBehalfOf user with allowance. Should revert since stable borrowing is disabled.', async () => { const { dai, pool, weth, users, helpersContract } = testEnv; const caller = users[5]; @@ -462,14 +531,14 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { const reserveData = await pool.getReserveData(weth.address); - const stableDebtToken = await getVariableDebtToken(reserveData.stableDebtTokenAddress); + const stableDebtToken = await getStableDebtToken(reserveData.stableDebtTokenAddress); // Deposited for onBehalfOf user already, delegate borrow allowance await stableDebtToken.connect(onBehalfOf.signer).approveDelegation(caller.address, flashAmount); await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - await pool + await expect(pool .connect(caller.signer) .flashLoan( _mockFlashLoanReceiver.address, @@ -479,7 +548,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { onBehalfOf.address, '0x10', '0' - ); + )).to.be.revertedWith(VL_STABLE_BORROWING_NOT_ENABLED); const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address @@ -490,7 +559,50 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { const onBehalfOfDebt = await wethDebtToken.balanceOf(onBehalfOf.address); expect(onBehalfOfDebt.toString()).to.be.equal( - '800000000000000000', + '0', + 'Invalid onBehalfOf user debt' + ); + }); + + it('Caller takes a WETH flashloan with mode = 2 onBehalfOf user with allowance. A loan for onBehalfOf is created.', async () => { + const { dai, pool, weth, users, helpersContract } = testEnv; + + const caller = users[5]; + const onBehalfOf = users[4]; + + const flashAmount = ethers.utils.parseEther('0.8'); + + const reserveData = await pool.getReserveData(weth.address); + + const variableDebtToken = await getVariableDebtToken(reserveData.variableDebtTokenAddress); + + // Deposited for onBehalfOf user already, delegate borrow allowance + await variableDebtToken.connect(onBehalfOf.signer).approveDelegation(caller.address, flashAmount); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + await expect(pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [flashAmount], + [2], + onBehalfOf.address, + '0x10', + '0' + )).to.not.be.reverted; + + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + + const wethDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + const onBehalfOfDebt = await wethDebtToken.balanceOf(onBehalfOf.address); + + expect(onBehalfOfDebt.toString()).to.be.equal( + ethers.utils.parseEther('0.8'), 'Invalid onBehalfOf user debt' ); }); diff --git a/test-suites/test-lp/liquidation-atoken.spec.ts b/test-suites/test-lp/liquidation-atoken.spec.ts index 1b6f9911..90296edb 100644 --- a/test-suites/test-lp/liquidation-atoken.spec.ts +++ b/test-suites/test-lp/liquidation-atoken.spec.ts @@ -230,7 +230,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) => ).to.be.true; }); - it('User 3 deposits 1000 USDC, user 4 1 WETH, user 4 borrows - drops HF, liquidates the borrow', async () => { + it('User 3 deposits 1000 USDC, user 4 1 WETH, user 4 borrows at variable - drops HF, liquidates the borrow', async () => { const { users, pool, usdc, oracle, weth, helpersContract } = testEnv; const depositor = users[3]; const borrower = users[4]; @@ -278,7 +278,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) => await pool .connect(borrower.signer) - .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); + .borrow(usdc.address, amountUSDCToBorrow, RateMode.Variable, '0', borrower.address); //drops HF below 1 @@ -302,7 +302,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) => const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address); const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); - const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + const amountToLiquidate = new BigNumber(userReserveDataBefore.currentVariableDebt.toString()) .multipliedBy(0.5) .toFixed(0); @@ -345,8 +345,8 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) => 'Invalid health factor' ); - expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( - new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + expect(userReserveDataAfter.currentVariableDebt.toString()).to.be.bignumber.almostEqual( + new BigNumber(userReserveDataBefore.currentVariableDebt.toString()) .minus(amountToLiquidate) .toFixed(0), 'Invalid user borrow balance after liquidation' diff --git a/test-suites/test-lp/liquidation-underlying.spec.ts b/test-suites/test-lp/liquidation-underlying.spec.ts index 0c9c4adf..b86a55d6 100644 --- a/test-suites/test-lp/liquidation-underlying.spec.ts +++ b/test-suites/test-lp/liquidation-underlying.spec.ts @@ -5,8 +5,8 @@ import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../../helpers/constants' import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; import { makeSuite } from './helpers/make-suite'; import { ProtocolErrors, RateMode } from '../../helpers/types'; -import { calcExpectedStableDebtTokenBalance } from './helpers/utils/calculations'; -import { getUserData } from './helpers/utils/helpers'; +import { calcExpectedVariableDebtTokenBalance } from './helpers/utils/calculations'; +import { getReserveData, getUserData } from './helpers/utils/helpers'; import { CommonsConfig } from '../../markets/lp/commons'; import { parseEther } from 'ethers/lib/utils'; @@ -91,7 +91,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', await pool .connect(borrower.signer) - .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address); + .borrow(dai.address, amountDAIToBorrow, RateMode.Variable, '0', borrower.address); const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); @@ -131,6 +131,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', //approve protocol to access the liquidator wallet await dai.connect(liquidator.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + const daiReserveBefore = await getReserveData(helpersContract, dai.address); const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); @@ -185,16 +186,15 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', const txTimestamp = new BigNumber( (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp ); - - const stableDebtBeforeTx = calcExpectedStableDebtTokenBalance( - userReserveDataBefore.principalStableDebt, - userReserveDataBefore.stableBorrowRate, - userReserveDataBefore.stableRateLastUpdated, + const reserve = await getReserveData + const variableDebtBeforeTx = calcExpectedVariableDebtTokenBalance( + daiReserveBefore, + userReserveDataBefore, txTimestamp ); expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( - stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), + variableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), 'Invalid user debt after liquidation' ); @@ -275,7 +275,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', await pool .connect(borrower.signer) - .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); + .borrow(usdc.address, amountUSDCToBorrow, RateMode.Variable, '0', borrower.address); //drops HF below 1 await oracle.setAssetPrice( From d0a1ea71719552eea78930e7bf3b04fd1564347c Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Tue, 9 Feb 2021 18:14:38 -0500 Subject: [PATCH 087/219] Adapted test suite and added some tests for LP market --- test-suites/test-aave/flashloan.spec.ts | 2 +- .../scenarios/borrow-repay-stable.json | 106 +++++++++++++++--- .../scenarios/borrow-repay-variable.json | 15 ++- .../helpers/scenarios/credit-delegation.json | 33 +++++- .../scenarios/rebalance-stable-rate.json | 8 +- .../helpers/scenarios/swap-rate-mode.json | 62 +++++++++- .../helpers/scenarios/withdraw-negatives.json | 52 ++++++++- .../test-lp/helpers/scenarios/withdraw.json | 96 +++++++++++++++- .../test-lp/liquidation-underlying.spec.ts | 16 +-- .../test-lp/pausable-functions.spec.ts | 14 +-- test-suites/test-lp/weth-gateway.spec.ts | 36 +++--- 11 files changed, 376 insertions(+), 64 deletions(-) diff --git a/test-suites/test-aave/flashloan.spec.ts b/test-suites/test-aave/flashloan.spec.ts index 4a5f5576..911c4adc 100644 --- a/test-suites/test-aave/flashloan.spec.ts +++ b/test-suites/test-aave/flashloan.spec.ts @@ -462,7 +462,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { const reserveData = await pool.getReserveData(weth.address); - const stableDebtToken = await getVariableDebtToken(reserveData.stableDebtTokenAddress); + const stableDebtToken = await getStableDebtToken(reserveData.stableDebtTokenAddress); // Deposited for onBehalfOf user already, delegate borrow allowance await stableDebtToken.connect(onBehalfOf.signer).approveDelegation(caller.address, flashAmount); diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json b/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json index 00596048..a1402942 100644 --- a/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json +++ b/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json @@ -3,7 +3,7 @@ "description": "Test cases for the borrow function, stable mode.", "stories": [ { - "description": "User 0 deposits 1000 LPDAI, user 1 deposits 1 WETH as collateral and borrows 100 LPDAI at stable rate", + "description": "User 0 deposits 1000 LPDAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 LPDAI at stable rate (revert expected)", "actions": [ { "name": "mint", @@ -67,7 +67,7 @@ "user": "1", "timeTravel": "365" }, - "expected": "success" + "expected": "revert" } ] }, @@ -83,12 +83,43 @@ "user": "1" }, "expected": "revert", - "revertMessage": "There is not enough collateral to cover a new borrow" + "revertMessage": "12" } ] }, { - "description": "User 1 repays half of the LPDAI borrow after one year", + "description": "User 1 tries to borrow 100 LPDAI at variable", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "LPDAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 tries to borrow the rest of the LPDAI liquidity at stable (revert expected)", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "LPDAI", + "amount": "900", + "borrowRateMode": "stable", + "user": "1" + }, + "expected": "revert", + "revertMessage": "12" + } + ] + }, + { + "description": "User 1 repays half of the LPDAI borrow at stable after one year (revert expected)", "actions": [ { "name": "mint", @@ -117,12 +148,28 @@ "onBehalfOf": "1", "borrowRateMode": "stable" }, + "expected": "revert" + } + ] + }, + { + "description": "User 1 repays half of the variable LPDAI borrow after one year", + "actions": [ + { + "name": "repay", + "args": { + "reserve": "LPDAI", + "amount": "50", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, "expected": "success" } ] }, { - "description": "User 1 repays the rest of the LPDAI borrow after one year", + "description": "User 1 repays the rest of the LPDAI borrow at stable after one year (revert expected)", "actions": [ { "name": "mint", @@ -151,6 +198,22 @@ "onBehalfOf": "1", "borrowRateMode": "stable" }, + "expected": "revert" + } + ] + }, + { + "description": "User 1 repays the rest of the LPDAI borrow after one year at variable", + "actions": [ + { + "name": "repay", + "args": { + "reserve": "LPDAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, "expected": "success" } ] @@ -221,7 +284,7 @@ ] }, { - "description": "User 0 deposits 1000 LPDAI, user 1,2,3,4 deposit 1 WETH each and borrow 100 LPDAI at stable rate. Everything is repaid, user 0 withdraws", + "description": "User 0 deposits 1000 LPDAI, user 1,2,3,4 deposit 1 WETH each and borrow 100 LPDAI at stable rate (revert expected) user 0 withdraws", "actions": [ { "name": "mint", @@ -284,7 +347,7 @@ "user": "1", "timeTravel": "365" }, - "expected": "success" + "expected": "revert" }, { "name": "mint", @@ -321,7 +384,7 @@ "user": "2", "timeTravel": "365" }, - "expected": "success" + "expected": "revert" }, { "name": "mint", @@ -358,7 +421,7 @@ "user": "3", "timeTravel": "365" }, - "expected": "success" + "expected": "revert" }, { "name": "mint", @@ -395,7 +458,7 @@ "user": "4", "timeTravel": "365" }, - "expected": "success" + "expected": "revert" }, { "name": "mint", @@ -424,7 +487,7 @@ "onBehalfOf": "1", "borrowRateMode": "stable" }, - "expected": "success" + "expected": "revert" }, { "name": "mint", @@ -453,7 +516,7 @@ "onBehalfOf": "2", "borrowRateMode": "stable" }, - "expected": "success" + "expected": "revert" }, { "name": "mint", @@ -482,7 +545,7 @@ "onBehalfOf": "3", "borrowRateMode": "stable" }, - "expected": "success" + "expected": "revert" }, { "name": "mint", @@ -511,7 +574,7 @@ "onBehalfOf": "4", "borrowRateMode": "stable" }, - "expected": "success" + "expected": "revert" }, { "name": "withdraw", @@ -525,7 +588,7 @@ ] }, { - "description": "User 0 deposits 1000 LPDAI, user 1 deposits 2 WETH and borrow 100 LPDAI at stable rate first, then 100 LPDAI at variable rate, repays everything. User 0 withdraws", + "description": "User 0 deposits 1000 LPDAI, user 1 deposits 2 WETH and borrow 100 LPDAI at stable rate first (revert expected), then 100 LPDAI at variable rate twice, repays everything. User 0 withdraws", "actions": [ { "name": "mint", @@ -588,6 +651,17 @@ "user": "1", "timeTravel": "365" }, + "expected": "revert" + }, + { + "name": "borrow", + "args": { + "reserve": "LPDAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "1", + "timeTravel": "365" + }, "expected": "success" }, { @@ -628,7 +702,7 @@ "onBehalfOf": "1", "borrowRateMode": "stable" }, - "expected": "success" + "expected": "revert" }, { "name": "repay", diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json b/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json index 743ef2e8..1ffc911b 100644 --- a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json +++ b/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json @@ -814,7 +814,7 @@ ] }, { - "description": "User 0 deposits 1000 LPDAI, user 6 deposits 2 WETH and borrow 100 LPDAI at variable rate first, then 100 LPDAI at stable rate, repays everything. User 0 withdraws", + "description": "User 0 deposits 1000 LPDAI, user 6 deposits 2 WETH and borrow 100 LPDAI at variable rate first, then 100 LPDAI at stable rate (revert expected), then 100 LPDAI at variable again, repays everything. User 0 withdraws", "actions": [ { "name": "mint", @@ -888,6 +888,17 @@ "user": "6", "timeTravel": "365" }, + "expected": "revert" + }, + { + "name": "borrow", + "args": { + "reserve": "LPDAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "6", + "timeTravel": "365" + }, "expected": "success" }, { @@ -917,7 +928,7 @@ "onBehalfOf": "6", "borrowRateMode": "stable" }, - "expected": "success" + "expected": "revert" }, { "name": "repay", diff --git a/test-suites/test-lp/helpers/scenarios/credit-delegation.json b/test-suites/test-lp/helpers/scenarios/credit-delegation.json index cb8e82d6..46437c40 100644 --- a/test-suites/test-lp/helpers/scenarios/credit-delegation.json +++ b/test-suites/test-lp/helpers/scenarios/credit-delegation.json @@ -82,7 +82,7 @@ ] }, { - "description": "User 4 trying to borrow 1 WETH stable on behalf of user 0, revert expected", + "description": "User 4 trying to borrow 1 WETH stable on behalf of user 0, (revert expected)", "actions": [ { "name": "borrow", @@ -99,7 +99,7 @@ ] }, { - "description": "User 0 delegates borrowing of 1 WETH to user 4, user 4 borrows 3 WETH variable on behalf of user 0, revert expected", + "description": "User 0 delegates borrowing of 1 WETH to user 4, user 4 borrows 3 WETH variable on behalf of user 0, (revert expected)", "actions": [ { "name": "delegateBorrowAllowance", @@ -127,7 +127,7 @@ ] }, { - "description": "User 0 delegates borrowing of 1 WETH on stable to user 2, user 2 borrows 1 WETH stable on behalf of user 0", + "description": "User 0 delegates borrowing of 1 WETH on stable to user 2, user 2 borrows 1 WETH stable on behalf of user 0 (revert expected)", "actions": [ { "name": "delegateBorrowAllowance", @@ -149,6 +149,33 @@ "onBehalfOf": "0", "borrowRateMode": "stable" }, + "expected": "revert" + } + ] + }, + { + "description": "User 0 delegates borrowing of 1 WETH on variable to user 2, user 2 borrows 1 WETH variable on behalf of user 0", + "actions": [ + { + "name": "delegateBorrowAllowance", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0", + "borrowRateMode": "variable", + "toUser": "2" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "2", + "onBehalfOf": "0", + "borrowRateMode": "variable" + }, "expected": "success" } ] diff --git a/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json b/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json index 6c9325ef..21c09510 100644 --- a/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json +++ b/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json @@ -18,7 +18,7 @@ ] }, { - "description": "User 0 deposits 1000 LPUSDC, user 1 deposits 7 WETH, borrows 250 LPUSDC at a stable rate, user 0 rebalances user 1 (revert expected)", + "description": "User 0 deposits 1000 LPUSDC, user 1 deposits 7 WETH, borrows 250 LPUSDC at a variable rate, user 0 rebalances user 1 (revert expected)", "actions": [ { "name": "mint", @@ -77,7 +77,7 @@ "args": { "reserve": "LPUSDC", "amount": "250", - "borrowRateMode": "stable", + "borrowRateMode": "variable", "user": "1" }, "expected": "success" @@ -171,7 +171,7 @@ }, { - "description": "User 1 borrows the remaining LPUSDC (usage ratio = 100%) at variable. User 0 rebalances user 1", + "description": "User 1 borrows the remaining LPUSDC (usage ratio = 100%) at variable. User 0 rebalances user 1, fails since there are no stable borrows (revert expected)", "actions": [ { "name": "borrow", @@ -190,7 +190,7 @@ "user": "0", "target": "1" }, - "expected": "success" + "expected": "revert" } ] } diff --git a/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json b/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json index 98011e48..82b44e83 100644 --- a/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json +++ b/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json @@ -33,7 +33,7 @@ ] }, { - "description": "User 0 deposits 1000 LPDAI, user 1 deposits 2 WETH as collateral, borrows 100 LPDAI at variable rate and swaps to stable after one year", + "description": "User 0 deposits 1000 LPDAI, user 1 deposits 2 WETH as collateral, borrows 100 LPDAI at variable rate and swaps to stable after one year, fails because stable borrowing is disabled (revert expected)", "actions": [ { "name": "mint", @@ -105,12 +105,12 @@ "user": "1", "borrowRateMode": "variable" }, - "expected": "success" + "expected": "revert" } ] }, { - "description": "User 1 borrows another 100 LPDAI, and swaps back to variable after one year, repays the loan", + "description": "User 1 borrows another 100 LPDAI at stable (revert expected), and swaps back to variable after one year (revert expected), repays the loan", "actions": [ { "name": "borrow", @@ -121,6 +121,60 @@ "user": "1", "timeTravel": "365" }, + "expected": "revert" + }, + { + "name": "swapBorrowRateMode", + "args": { + "reserve": "LPDAI", + "user": "1", + "borrowRateMode": "stable" + }, + "expected": "revert" + }, + { + "name": "mint", + "description": "Mint 50 LPDAI to cover the interest", + "args": { + "reserve": "LPDAI", + "amount": "50", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "LPDAI", + "user": "1" + }, + "expected": "success" + }, + { + "name": "repay", + "args": { + "reserve": "LPDAI", + "amount": "-1", + "user": "1", + "onBehalfOf": "1", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 1 borrows another 100 LPDAI at variable, and tries to swap to stable after one year (revert expected), repays the loan", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "LPDAI", + "amount": "100", + "borrowRateMode": "variable", + "user": "1", + "timeTravel": "365" + }, "expected": "success" }, { @@ -130,7 +184,7 @@ "user": "1", "borrowRateMode": "stable" }, - "expected": "success" + "expected": "revert" }, { "name": "mint", diff --git a/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json b/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json index 1d7ba442..e282e65c 100644 --- a/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json +++ b/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json @@ -60,7 +60,7 @@ ] }, { - "description": "Users 1 deposits 1 WETH, borrows 100 LPDAI, tries to redeem the 1 WETH deposited (revert expected)", + "description": "Users 1 deposits 1 WETH, borrows 100 LPDAI stable (revert expected), redeems the 1 WETH deposited", "actions": [ { "name": "mint", @@ -96,6 +96,56 @@ "user": "1", "borrowRateMode": "stable" }, + "expected": "revert" + }, + { + "name": "withdraw", + "args": { + "reserve": "WETH", + "amount": "-1", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "Users 1 deposits 1 WETH, borrows 100 LPDAI at variable rate, tries to redeem the 1 WETH deposited (revert expected)", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "LPDAI", + "amount": "100", + "user": "1", + "borrowRateMode": "variable" + }, "expected": "success" }, { diff --git a/test-suites/test-lp/helpers/scenarios/withdraw.json b/test-suites/test-lp/helpers/scenarios/withdraw.json index 78ec38ca..ac72b2c6 100644 --- a/test-suites/test-lp/helpers/scenarios/withdraw.json +++ b/test-suites/test-lp/helpers/scenarios/withdraw.json @@ -238,7 +238,7 @@ ] }, { - "description": "Users 0 deposits 1000 LPDAI, user 1 Deposit 1000 LPUSDC and 1 WETH, borrows 100 LPDAI. User 1 tries to withdraw all the LPUSDC", + "description": "Users 0 deposits 1000 LPDAI, user 1 Deposit 1000 LPUSDC and 1 WETH, borrows 100 LPDAI at stable rate (revert expected). User 1 tries to withdraw all the LPUSDC", "actions": [ { "name": "deposit", @@ -309,6 +309,100 @@ "user": "1", "borrowRateMode": "stable" }, + "expected": "revert" + }, + { + "name": "withdraw", + "args": { + "reserve": "LPUSDC", + "amount": "-1", + "user": "1" + }, + "expected": "success" + } + ] + }, + { + "description": "Users 0 deposits 1000 LPDAI, user 1 Deposit 1000 LPUSDC and 1 WETH, borrows 100 LPDAI at variable rate. User 1 tries to withdraw all the LPUSDC", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "LPDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "LPDAI", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "LPUSDC", + "amount": "10000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "LPUSDC", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "LPUSDC", + "amount": "1000", + "user": "1" + }, + "expected": "success" + }, + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "1" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "1" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "LPDAI", + "amount": "100", + "user": "1", + "borrowRateMode": "variable" + }, "expected": "success" }, { diff --git a/test-suites/test-lp/liquidation-underlying.spec.ts b/test-suites/test-lp/liquidation-underlying.spec.ts index b86a55d6..7bc78dad 100644 --- a/test-suites/test-lp/liquidation-underlying.spec.ts +++ b/test-suites/test-lp/liquidation-underlying.spec.ts @@ -142,7 +142,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', borrower.address ); - const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); + const amountToLiquidate = userReserveDataBefore.currentVariableDebt.div(2).toFixed(0); await increaseTime(100); @@ -193,7 +193,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', txTimestamp ); - expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( + expect(userReserveDataAfter.currentVariableDebt.toString()).to.be.bignumber.almostEqual( variableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), 'Invalid user debt after liquidation' ); @@ -301,7 +301,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); const amountToLiquidate = DRE.ethers.BigNumber.from( - userReserveDataBefore.currentStableDebt.toString() + userReserveDataBefore.currentVariableDebt.toString() ) .div(2) .toString(); @@ -344,8 +344,8 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', 'Invalid health factor' ); - expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( - new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + expect(userReserveDataAfter.currentVariableDebt.toString()).to.be.bignumber.almostEqual( + new BigNumber(userReserveDataBefore.currentVariableDebt.toString()) .minus(amountToLiquidate) .toFixed(0), 'Invalid user borrow balance after liquidation' @@ -421,7 +421,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address); const aaveReserveDataBefore = await helpersContract.getReserveData(aave.address); - const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + const amountToLiquidate = new BigNumber(userReserveDataBefore.currentVariableDebt.toString()) .div(2) .decimalPlaces(0, BigNumber.ROUND_DOWN) .toFixed(0); @@ -468,8 +468,8 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', 'Invalid health factor' ); - expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( - new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + expect(userReserveDataAfter.currentVariableDebt.toString()).to.be.bignumber.almostEqual( + new BigNumber(userReserveDataBefore.currentVariableDebt.toString()) .minus(expectedPrincipal) .toFixed(0), 'Invalid user borrow balance after liquidation' diff --git a/test-suites/test-lp/pausable-functions.spec.ts b/test-suites/test-lp/pausable-functions.spec.ts index c95aaf3c..2096b235 100644 --- a/test-suites/test-lp/pausable-functions.spec.ts +++ b/test-suites/test-lp/pausable-functions.spec.ts @@ -131,7 +131,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { // Try to execute liquidation await expect( - pool.connect(user.signer).borrow(dai.address, '1', '1', '0', user.address) + pool.connect(user.signer).borrow(dai.address, '1', '2', '0', user.address) ).revertedWith(LP_IS_PAUSED); // Unpause the pool @@ -146,7 +146,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { await configurator.connect(users[1].signer).setPoolPause(true); // Try to execute liquidation - await expect(pool.connect(user.signer).repay(dai.address, '1', '1', user.address)).revertedWith( + await expect(pool.connect(user.signer).repay(dai.address, '1', '2', user.address)).revertedWith( LP_IS_PAUSED ); @@ -173,7 +173,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [flashAmount], - [1], + [2], caller.address, '0x10', '0' @@ -232,7 +232,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { await pool .connect(borrower.signer) - .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); + .borrow(usdc.address, amountUSDCToBorrow, RateMode.Variable, '0', borrower.address); // Drops HF below 1 await oracle.setAssetPrice( @@ -249,7 +249,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { borrower.address ); - const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + const amountToLiquidate = new BigNumber(userReserveDataBefore.currentVariableDebt.toString()) .multipliedBy(0.5) .toFixed(0); @@ -265,7 +265,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { await configurator.connect(users[1].signer).setPoolPause(false); }); - it('SwapBorrowRateMode', async () => { + it('SwapBorrowRateMode should fail because pool is paused', async () => { const { pool, weth, dai, usdc, users, configurator } = testEnv; const user = users[1]; const amountWETHToDeposit = parseEther('10'); @@ -294,7 +294,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { await configurator.connect(users[1].signer).setPoolPause(false); }); - it('RebalanceStableBorrowRate', async () => { + it('RebalanceStableBorrowRate should fail because the pool is paused, even if there is no stable borrow', async () => { const { pool, dai, users, configurator } = testEnv; const user = users[1]; // Pause pool diff --git a/test-suites/test-lp/weth-gateway.spec.ts b/test-suites/test-lp/weth-gateway.spec.ts index 22939f5c..b8a0216a 100644 --- a/test-suites/test-lp/weth-gateway.spec.ts +++ b/test-suites/test-lp/weth-gateway.spec.ts @@ -6,6 +6,7 @@ import { DRE, waitForTx } from '../../helpers/misc-utils'; import { BigNumber } from 'ethers'; import { getStableDebtToken, getVariableDebtToken } from '../../helpers/contracts-getters'; import { deploySelfdestructTransferMock } from '../../helpers/contracts-deployments'; +import { ProtocolErrors } from '../../helpers/types'; const { expect } = require('chai'); @@ -101,7 +102,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => expect(afterFullATokensBalance).to.be.eq(0, 'User aWETH balance should be zero'); }); - it('Borrow stable WETH and Full Repay with ETH', async () => { + it('Borrowing stable WETH should fail since stable borrowing is disabled', async () => { const { users, wethGateway, aDai, weth, dai, pool, helpersContract } = testEnv; const borrowSize = parseEther('1'); const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); @@ -130,27 +131,28 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => expect(aTokensBalance).to.be.gte(daiSize); // Borrow WETH with WETH as collateral - await waitForTx( - await pool.connect(user.signer).borrow(weth.address, borrowSize, '1', '0', user.address) - ); + + await expect(pool.connect(user.signer).borrow(weth.address, borrowSize, '1', '0', user.address)) + .to.be.revertedWith(ProtocolErrors.VL_STABLE_BORROWING_NOT_ENABLED); - const debtBalance = await stableDebtToken.balanceOf(user.address); - expect(debtBalance).to.be.gt(zero); + // const debtBalance = await stableDebtToken.balanceOf(user.address); - // Full Repay WETH with native ETH - await waitForTx( - await wethGateway - .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) - ); + // expect(debtBalance).to.be.gt(zero); - const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); - expect(debtBalanceAfterRepay).to.be.eq(zero); + // // Full Repay WETH with native ETH + // await waitForTx( + // await wethGateway + // .connect(user.signer) + // .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) + // ); - // Withdraw DAI - await aDai.connect(user.signer).approve(pool.address, MAX_UINT_AMOUNT); - await pool.connect(user.signer).withdraw(dai.address, MAX_UINT_AMOUNT, user.address); + // const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); + // expect(debtBalanceAfterRepay).to.be.eq(zero); + + // // Withdraw DAI + // await aDai.connect(user.signer).approve(pool.address, MAX_UINT_AMOUNT); + // await pool.connect(user.signer).withdraw(dai.address, MAX_UINT_AMOUNT, user.address); }); it('Borrow variable WETH and Full Repay with ETH', async () => { From 4b39c4216934cf270379ab4f33a6a1a09099409b Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 10 Feb 2021 13:52:51 -0500 Subject: [PATCH 088/219] Unoptimized but functional light deployment --- helpers/contracts-deployments.ts | 18 ++ helpers/init-helpers.ts | 260 ++++++++++++++-------------- helpers/types.ts | 1 + markets/aave/reservesConfigs.ts | 20 +++ markets/lp/reservesConfigs.ts | 21 ++- package.json | 4 +- tasks/full/5_initialize.ts | 2 +- test-suites/test-lp/__setup.spec.ts | 18 +- 8 files changed, 203 insertions(+), 141 deletions(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index d6133108..2406c065 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -378,6 +378,15 @@ export const deployGenericAToken = async ( return instance; }; +export const deployGenericATokenImpl = async ( + verify: boolean +) => withSaveAndVerify( + await new ATokenFactory(await getFirstSigner()).deploy(), + eContractid.AToken, + [], + verify + ); + export const deployDelegationAwareAToken = async ( [pool, underlyingAssetAddress, treasuryAddress, incentivesController, name, symbol]: [ tEthereumAddress, @@ -409,6 +418,15 @@ export const deployDelegationAwareAToken = async ( return instance; }; +export const deployDelegationAwareATokenImpl = async ( + verify: boolean +) => withSaveAndVerify( + await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(), + eContractid.DelegationAwareAToken, + [], + verify + ); + export const deployAllMockTokens = async (verify?: boolean) => { const tokens: { [symbol: string]: MockContract | MintableERC20 } = {}; diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 39af12ed..d06faf99 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -20,12 +20,15 @@ import { BigNumber, BigNumberish, Signer } from 'ethers'; import { deployDefaultReserveInterestRateStrategy, deployDelegationAwareAToken, + deployDelegationAwareATokenImpl, deployGenericAToken, + deployGenericATokenImpl, deployStableDebtToken, deployVariableDebtToken, } from './contracts-deployments'; import { ZERO_ADDRESS } from './constants'; import { isZeroAddress } from 'ethereumjs-util'; +import { DefaultReserveInterestRateStrategy, DelegationAwareAToken } from '../types'; export const chooseATokenDeployment = (id: eContractid) => { switch (id) { @@ -55,18 +58,11 @@ export const initReservesByHelper = async ( // Set aTokenAndRatesDeployer as temporal admin await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address)); - + console.log("Got deployer address"); // CHUNK CONFIGURATION const tokensChunks = 2; const initChunks = 4; - // Deploy tokens and rates that uses common aToken in chunks - const reservesChunks = chunk( - Object.entries(reservesParams).filter( - ([_, { aTokenImpl }]) => aTokenImpl === eContractid.AToken - ) as [string, IReserveParams][], - tokensChunks - ); // Initialize variables for future reserves initialization let deployedStableTokens: string[] = []; let deployedVariableTokens: string[] = []; @@ -94,42 +90,87 @@ export const initReservesByHelper = async ( stableDebtTokenSymbol: string, }[] = []; + //let lastStrategy: string = ""; + let strategyRates: [ + string, // addresses provider + string, + string, + string, + string, + string, + string + ]; + // TEST - replacing with two maps, like a mapping to mapping in solidity + let rateStrategies: Record = {}; + let strategyAddresses: Record = {}; + let strategyAddressPerAsset: Record = {}; + let aTokenType: Record = {}; + let delegationAwareATokenImplementationAddress = ""; + let aTokenImplementationAddress = ""; + let stableDebtTokenImplementationAddress = ""; + let variableDebtTokenImplementationAddress = ""; + // --TEST + + const tx1 = await waitForTx( + await stableAndVariableDeployer.initDeployment([ZERO_ADDRESS], ["1"]) + ); + tx1.events?.forEach((event, index) => { + stableDebtTokenImplementationAddress = event?.args?.stableToken; + variableDebtTokenImplementationAddress = event?.args?.variableToken; + rawInsertContractAddressInDb(`stableDebtTokenImpl`, stableDebtTokenImplementationAddress); + rawInsertContractAddressInDb(`variableDebtTokenImpl`, variableDebtTokenImplementationAddress); + }); + + + const aTokenImplementation = await deployGenericATokenImpl(verify); + aTokenImplementationAddress = aTokenImplementation.address; + rawInsertContractAddressInDb(`aTokenImpl`, aTokenImplementationAddress); + // Deploy delegated aware reserves tokens + const delegatedAwareReserves = Object.entries(reservesParams).filter( + ([_, { aTokenImpl }]) => aTokenImpl === eContractid.DelegationAwareAToken + ) as [string, IReserveParams][]; + + if (delegatedAwareReserves.length > 0) { + const delegationAwareATokenImplementation = await deployDelegationAwareATokenImpl(verify); + delegationAwareATokenImplementationAddress = delegationAwareATokenImplementation.address; + rawInsertContractAddressInDb(`delegationAwareATokenImpl`, delegationAwareATokenImplementationAddress); + } + + // Deploy tokens and rates that uses common aToken in chunks + const reservesChunks = chunk( + Object.entries(reservesParams).filter( + ([_, { aTokenImpl }]) => aTokenImpl === eContractid.AToken + ) as [string, IReserveParams][], + tokensChunks + ); + + // const reserves = Object.entries(reservesParams).filter( + // ([_, { aTokenImpl }]) => aTokenImpl === eContractid.AToken + // ) as [string, IReserveParams][]; + + console.log( `- Token deployments in ${reservesChunks.length * 2} txs instead of ${ Object.entries(reservesParams).length * 4 } txs` ); - + // All of these use the same aToken implementation + // but they might use different rate strategy implementations, + // it is better to simply iterate through every reserve instead of chunks later for (let reservesChunk of reservesChunks) { + // Prepare data const tokens: string[] = []; const symbols: string[] = []; - const strategyRates: [ - BigNumberish, - BigNumberish, - BigNumberish, - BigNumberish, - BigNumberish, - BigNumberish - ][] = []; + const reservesDecimals: string[] = []; - const inputParams: { - asset: string, - rates: [ - BigNumberish, - BigNumberish, - BigNumberish, - BigNumberish, - BigNumberish, - BigNumberish - ] - }[] = []; - for (let [assetSymbol, { reserveDecimals }] of reservesChunk) { + const assetAddressIndex = Object.keys(tokenAddresses).findIndex( (value) => value === assetSymbol ); + const [, tokenAddress] = (Object.entries(tokenAddresses) as [string, string][])[ assetAddressIndex ]; @@ -137,9 +178,11 @@ export const initReservesByHelper = async ( const reserveParamIndex = Object.keys(reservesParams).findIndex( (value) => value === assetSymbol ); + const [ , { + strategy, optimalUtilizationRate, baseVariableBorrowRate, variableRateSlope1, @@ -149,76 +192,55 @@ export const initReservesByHelper = async ( }, ] = (Object.entries(reservesParams) as [string, IReserveParams][])[reserveParamIndex]; // Add to lists + tokens.push(tokenAddress); symbols.push(assetSymbol); - strategyRates.push([ - optimalUtilizationRate, - baseVariableBorrowRate, - variableRateSlope1, - variableRateSlope2, - stableRateSlope1, - stableRateSlope2, - ]); - reservesDecimals.push(reserveDecimals); - inputParams.push({ - asset: tokenAddress, - rates: [ + if (!strategyAddresses[strategy]) { + // Strategy does not exist, create a new one + rateStrategies[strategy] = [ + addressProvider.address, optimalUtilizationRate, baseVariableBorrowRate, variableRateSlope1, variableRateSlope2, stableRateSlope1, - stableRateSlope2 - ] - }); + stableRateSlope2, + ]; + //lastStrategy = strategy; + strategyAddresses[strategy] = (await deployDefaultReserveInterestRateStrategy( + rateStrategies[strategy], + verify + )).address; + } + strategyAddressPerAsset[assetSymbol] = strategyAddresses[strategy]; + console.log("Strategy address for asset %s: %s", assetSymbol, strategyAddressPerAsset[assetSymbol]) + + reservesDecimals.push(reserveDecimals); + aTokenType[assetSymbol] = "generic"; + // inputParams.push({ + // asset: tokenAddress, + // rates: [ + // optimalUtilizationRate, + // baseVariableBorrowRate, + // variableRateSlope1, + // variableRateSlope2, + // stableRateSlope1, + // stableRateSlope2 + // ] + // }); } - - // Deploy stable and variable deployers and save implementations - const tx1 = await waitForTx( - await stableAndVariableDeployer.initDeployment(tokens, symbols) - ); - tx1.events?.forEach((event, index) => { - rawInsertContractAddressInDb(`stableDebt${symbols[index]}`, event?.args?.stableToken); - rawInsertContractAddressInDb(`variableDebt${symbols[index]}`, event?.args?.variableToken); - }); - - // Deploy atokens and rate strategies and save implementations - const tx2 = await waitForTx( - await atokenAndRatesDeployer.initDeployment(inputParams) - ); - tx2.events?.forEach((event, index) => { - rawInsertContractAddressInDb(`a${symbols[index]}`, event?.args?.aToken); - rawInsertContractAddressInDb(`strategy${symbols[index]}`, event?.args?.strategy); - }); - - console.log(` - Deployed aToken, DebtTokens and Strategy for: ${symbols.join(', ')} `); - console.log(' * gasUsed: debtTokens batch', tx1.gasUsed.toString()); - console.log(' * gasUsed: aTokens and Strategy batch', tx2.gasUsed.toString()); - gasUsage = gasUsage.add(tx1.gasUsed).add(tx2.gasUsed); - - 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) || []; - - deployedStableTokens = [...deployedStableTokens, ...stableTokens]; - deployedVariableTokens = [...deployedVariableTokens, ...variableTokens]; - deployedATokens = [...deployedATokens, ...aTokens]; - deployedRates = [...deployedRates, ...strategies]; reserveInitDecimals = [...reserveInitDecimals, ...reservesDecimals]; reserveTokens = [...reserveTokens, ...tokens]; reserveSymbols = [...reserveSymbols, ...symbols]; } - // 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 aware aToken, debts tokens, and strategy`); const { + strategy, optimalUtilizationRate, baseVariableBorrowRate, variableRateSlope1, @@ -226,67 +248,49 @@ export const initReservesByHelper = async ( stableRateSlope1, stableRateSlope2, } = params; - const deployCustomAToken = chooseATokenDeployment(params.aTokenImpl); - const aToken = await deployCustomAToken( - [ - poolAddress, - tokenAddresses[symbol], - treasuryAddress, - ZERO_ADDRESS, - `Aave interest bearing ${symbol}`, - `a${symbol}`, - ], - verify - ); - const stableDebt = await deployStableDebtToken( - [ - poolAddress, - tokenAddresses[symbol], - ZERO_ADDRESS, // Incentives controller - `Aave stable debt bearing ${symbol}`, - `stableDebt${symbol}` - ], - verify - ); - const variableDebt = await deployVariableDebtToken( - [ - poolAddress, - tokenAddresses[symbol], - ZERO_ADDRESS, // Incentives controller - `Aave variable debt bearing ${symbol}`, - `variableDebt${symbol}`, - ], - verify - ); - const rates = await deployDefaultReserveInterestRateStrategy( - [ - tokenAddresses[symbol], + + if (!strategyAddresses[strategy]) { + // Strategy does not exist, create a new one + rateStrategies[strategy] = [ + addressProvider.address, optimalUtilizationRate, baseVariableBorrowRate, variableRateSlope1, variableRateSlope2, stableRateSlope1, stableRateSlope2, - ], - verify - ); + ]; + //lastStrategy = strategy; + strategyAddresses[strategy] = (await deployDefaultReserveInterestRateStrategy( + rateStrategies[strategy], + verify + )).address; + } + strategyAddressPerAsset[symbol] = strategyAddresses[strategy]; + console.log("Strategy address for asset %s: %s", symbol, strategyAddressPerAsset[symbol]) - deployedStableTokens.push(stableDebt.address); - deployedVariableTokens.push(variableDebt.address); - deployedATokens.push(aToken.address); - deployedRates.push(rates.address); + aTokenType[symbol] = "delegation aware"; reserveInitDecimals.push(params.reserveDecimals); reserveTokens.push(tokenAddresses[symbol]); reserveSymbols.push(symbol); } - for (let i = 0; i < deployedATokens.length; i ++) { + //gasUsage = gasUsage.add(tx1.gasUsed); + + for (let i = 0; i < reserveSymbols.length; i ++) { + let aTokenToUse: string; + if (aTokenType[reserveSymbols[i]] === 'generic') { + aTokenToUse = aTokenImplementationAddress; + } else { + aTokenToUse = delegationAwareATokenImplementationAddress; + } + initInputParams.push({ - aTokenImpl: deployedATokens[i], - stableDebtTokenImpl: deployedStableTokens[i], - variableDebtTokenImpl: deployedVariableTokens[i], + aTokenImpl: aTokenToUse, + stableDebtTokenImpl: stableDebtTokenImplementationAddress, + variableDebtTokenImpl: variableDebtTokenImplementationAddress, underlyingAssetDecimals: reserveInitDecimals[i], - interestRateStrategyAddress: deployedRates[i], + interestRateStrategyAddress: strategyAddressPerAsset[reserveSymbols[i]], underlyingAsset: reserveTokens[i], treasury: treasuryAddress, incentivesController: ZERO_ADDRESS, diff --git a/helpers/types.ts b/helpers/types.ts index 63295895..4a8b6475 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -329,6 +329,7 @@ export enum TokenContractId { export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { aTokenImpl: eContractid; reserveFactor: string; + strategy: string; } export interface IReserveBorrowParams { diff --git a/markets/aave/reservesConfigs.ts b/markets/aave/reservesConfigs.ts index 68ec93d6..213cb6cf 100644 --- a/markets/aave/reservesConfigs.ts +++ b/markets/aave/reservesConfigs.ts @@ -3,6 +3,7 @@ import { oneRay } from '../../helpers/constants'; import { eContractid, IReserveParams } from '../../helpers/types'; export const strategyBUSD: IReserveParams = { + strategy: "busd", optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(), @@ -20,6 +21,7 @@ export const strategyBUSD: IReserveParams = { }; export const strategyDAI: IReserveParams = { + strategy: "dai", optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(), @@ -37,6 +39,7 @@ export const strategyDAI: IReserveParams = { }; export const strategySUSD: IReserveParams = { + strategy: "susd", optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(), @@ -54,6 +57,7 @@ export const strategySUSD: IReserveParams = { }; export const strategyTUSD: IReserveParams = { + strategy: "tusd", optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(), @@ -71,6 +75,7 @@ export const strategyTUSD: IReserveParams = { }; export const strategyUSDC: IReserveParams = { + strategy: "usdc", optimalUtilizationRate: new BigNumber(0.9).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(), @@ -88,6 +93,7 @@ export const strategyUSDC: IReserveParams = { }; export const strategyUSDT: IReserveParams = { + strategy: "usdt", optimalUtilizationRate: new BigNumber(0.9).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(), @@ -105,6 +111,7 @@ export const strategyUSDT: IReserveParams = { }; export const strategyAAVE: IReserveParams = { + strategy: "aave", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: '0', variableRateSlope1: '0', @@ -122,6 +129,7 @@ export const strategyAAVE: IReserveParams = { }; export const strategyBAT: IReserveParams = { + strategy: "bat", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(), @@ -139,6 +147,7 @@ export const strategyBAT: IReserveParams = { }; export const strategyENJ: IReserveParams = { + strategy: "enj", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(), @@ -156,6 +165,7 @@ export const strategyENJ: IReserveParams = { }; export const strategyWETH: IReserveParams = { + strategy: "weth", optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(), @@ -173,6 +183,7 @@ export const strategyWETH: IReserveParams = { }; export const strategyKNC: IReserveParams = { + strategy: "knc", optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(), @@ -190,6 +201,7 @@ export const strategyKNC: IReserveParams = { }; export const strategyLINK: IReserveParams = { + strategy: "link", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(), @@ -207,6 +219,7 @@ export const strategyLINK: IReserveParams = { }; export const strategyMANA: IReserveParams = { + strategy: "mana", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(), @@ -224,6 +237,7 @@ export const strategyMANA: IReserveParams = { }; export const strategyMKR: IReserveParams = { + strategy: "mkr", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(), @@ -241,6 +255,7 @@ export const strategyMKR: IReserveParams = { }; export const strategyREN: IReserveParams = { + strategy: "ren", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(), @@ -258,6 +273,7 @@ export const strategyREN: IReserveParams = { }; export const strategySNX: IReserveParams = { + strategy: "snx", optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.12).multipliedBy(oneRay).toFixed(), @@ -275,6 +291,7 @@ export const strategySNX: IReserveParams = { }; export const strategyUNI: IReserveParams = { + strategy: "uni", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: '0', variableRateSlope1: '0', @@ -292,6 +309,7 @@ export const strategyUNI: IReserveParams = { }; export const strategyWBTC: IReserveParams = { + strategy: "wbtc", optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: '0', variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(), @@ -309,6 +327,7 @@ export const strategyWBTC: IReserveParams = { }; export const strategyYFI: IReserveParams = { + strategy: "yfi", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: '0', variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(), @@ -326,6 +345,7 @@ export const strategyYFI: IReserveParams = { }; export const strategyZRX: IReserveParams = { + strategy: "zrx", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: '0', variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(), diff --git a/markets/lp/reservesConfigs.ts b/markets/lp/reservesConfigs.ts index 9b78d748..a27261d0 100644 --- a/markets/lp/reservesConfigs.ts +++ b/markets/lp/reservesConfigs.ts @@ -3,6 +3,7 @@ import { oneRay } from '../../helpers/constants'; import { eContractid, IReserveParams } from '../../helpers/types'; export const strategyWETH: IReserveParams = { + strategy: 'WETH and WBTC', optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(), @@ -20,6 +21,7 @@ export const strategyWETH: IReserveParams = { }; export const strategyWBTC: IReserveParams = { + strategy: 'WETH and WBTC', optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(), @@ -37,12 +39,13 @@ export const strategyWBTC: IReserveParams = { }; export const strategyDAI: IReserveParams = { + strategy: 'stablecoin', 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(), + stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(), baseLTVAsCollateral: '7500', liquidationThreshold: '8000', liquidationBonus: '10500', @@ -54,6 +57,7 @@ export const strategyDAI: IReserveParams = { }; export const strategyUSDC: IReserveParams = { + strategy: 'stablecoin', optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(), @@ -71,6 +75,7 @@ export const strategyUSDC: IReserveParams = { }; export const strategyUSDT: IReserveParams = { + strategy: 'stablecoin', optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(), @@ -88,6 +93,7 @@ export const strategyUSDT: IReserveParams = { }; export const strategyDAIWETH: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -105,6 +111,7 @@ export const strategyDAIWETH: IReserveParams = { }; export const strategyWBTCWETH: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -122,6 +129,7 @@ export const strategyWBTCWETH: IReserveParams = { }; export const strategyAAVEWETH: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -139,6 +147,7 @@ export const strategyAAVEWETH: IReserveParams = { }; export const strategyBATWETH: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -156,6 +165,7 @@ export const strategyBATWETH: IReserveParams = { }; export const strategyUSDCDAI: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -173,6 +183,7 @@ export const strategyUSDCDAI: IReserveParams = { }; export const strategyCRVWETH: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -190,6 +201,7 @@ export const strategyCRVWETH: IReserveParams = { }; export const strategyLINKWETH: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -207,6 +219,7 @@ export const strategyLINKWETH: IReserveParams = { }; export const strategyMKRWETH: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -224,6 +237,7 @@ export const strategyMKRWETH: IReserveParams = { }; export const strategyRENWETH: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -241,6 +255,7 @@ export const strategyRENWETH: IReserveParams = { }; export const strategySNXWETH: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -258,6 +273,7 @@ export const strategySNXWETH: IReserveParams = { }; export const strategyUNIWETH: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -275,6 +291,7 @@ export const strategyUNIWETH: IReserveParams = { }; export const strategyUSDCWETH: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -292,6 +309,7 @@ export const strategyUSDCWETH: IReserveParams = { }; export const strategyWBTCUSDC: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), @@ -309,6 +327,7 @@ export const strategyWBTCUSDC: IReserveParams = { }; export const strategyYFIWETH: IReserveParams = { + strategy: 'uniswap LP base', optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), diff --git a/package.json b/package.json index 57f236fc..b2492041 100644 --- a/package.json +++ b/package.json @@ -39,12 +39,12 @@ "aave:evm:dev:migration": "npm run compile && hardhat aave:dev", "aave:docker:full:migration": "npm run compile && npm run hardhat:docker -- aave:mainnet", "aave:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- aave:mainnet --verify", - "lp:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- uniswap:mainnet --verify", + "lp:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- lp:mainnet --verify", "aave:kovan:full:initialize": "npm run hardhat:kovan -- full:initialize-lending-pool --verify --pool Aave", "aave:ropsten:full:migration": "npm run compile && npm run hardhat:ropsten -- aave:mainnet --verify", "aave:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- aave:mainnet", "aave:fork:main": "npm run compile && MAINNET_FORK=true hardhat aave:mainnet", - "lp:fork:main": "npm run compile && MAINNET_FORK=true hardhat uniswap:mainnet", + "lp:fork:main": "npm run compile && MAINNET_FORK=true hardhat lp:mainnet", "aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify", "aave:main:full:initialize": "npm run compile && MAINNET_FORK=true full:initialize-tokens --pool Aave", "prettier:check": "npx prettier -c 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test-suites/test-aave/**/*.ts'", diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 813a6a3e..438e3519 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -45,7 +45,7 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') } const treasuryAddress = await getTreasuryAddress(poolConfig); - + console.log("here"); await initReservesByHelper( ReservesConfig, reserveAssets, diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-lp/__setup.spec.ts index 47285ee0..72c5e01b 100644 --- a/test-suites/test-lp/__setup.spec.ts +++ b/test-suites/test-lp/__setup.spec.ts @@ -254,17 +254,17 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { ); await deployMockFlashLoanReceiver(addressesProvider.address); - // const mockUniswapRouter = await deployMockUniswapRouter(); + const mockUniswapRouter = await deployMockUniswapRouter(); - // const adapterParams: [string, string, string] = [ - // addressesProvider.address, - // mockUniswapRouter.address, - // mockTokens.WETH.address, - // ]; + const adapterParams: [string, string, string] = [ + addressesProvider.address, + mockUniswapRouter.address, + mockTokens.WETH.address, + ]; - // await deployUniswapLiquiditySwapAdapter(adapterParams); - // await deployUniswapRepayAdapter(adapterParams); - // await deployFlashLiquidationAdapter(adapterParams); + await deployUniswapLiquiditySwapAdapter(adapterParams); + await deployUniswapRepayAdapter(adapterParams); + await deployFlashLiquidationAdapter(adapterParams); await deployWalletBalancerProvider(); From fda95dd318be3da821e8652d8002ad4657785af5 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 10 Feb 2021 18:23:05 -0500 Subject: [PATCH 089/219] Added optimized deployment functionality --- helpers/init-helpers.ts | 205 ++++++++++---------------------- helpers/types.ts | 14 ++- markets/aave/rateStrategies.ts | 91 ++++++++++++++ markets/aave/reservesConfigs.ts | 175 +++++---------------------- markets/lp/rateStrategies.ts | 36 ++++++ markets/lp/reservesConfigs.ts | 162 ++++--------------------- tasks/verifications/2_tokens.ts | 2 +- 7 files changed, 260 insertions(+), 425 deletions(-) create mode 100644 markets/aave/rateStrategies.ts create mode 100644 markets/lp/rateStrategies.ts diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index d06faf99..de0e99f4 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -58,16 +58,11 @@ export const initReservesByHelper = async ( // Set aTokenAndRatesDeployer as temporal admin await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address)); - console.log("Got deployer address"); + // CHUNK CONFIGURATION - const tokensChunks = 2; const initChunks = 4; // Initialize variables for future reserves initialization - let deployedStableTokens: string[] = []; - let deployedVariableTokens: string[] = []; - let deployedATokens: string[] = []; - let deployedRates: string[] = []; let reserveTokens: string[] = []; let reserveInitDecimals: string[] = []; let reserveSymbols: string[] = []; @@ -100,7 +95,6 @@ export const initReservesByHelper = async ( string, string ]; - // TEST - replacing with two maps, like a mapping to mapping in solidity let rateStrategies: Record = {}; let strategyAddresses: Record = {}; let strategyAddressPerAsset: Record = {}; @@ -109,7 +103,6 @@ export const initReservesByHelper = async ( let aTokenImplementationAddress = ""; let stableDebtTokenImplementationAddress = ""; let variableDebtTokenImplementationAddress = ""; - // --TEST const tx1 = await waitForTx( await stableAndVariableDeployer.initDeployment([ZERO_ADDRESS], ["1"]) @@ -120,12 +113,13 @@ export const initReservesByHelper = async ( rawInsertContractAddressInDb(`stableDebtTokenImpl`, stableDebtTokenImplementationAddress); rawInsertContractAddressInDb(`variableDebtTokenImpl`, variableDebtTokenImplementationAddress); }); + //gasUsage = gasUsage.add(tx1.gasUsed); const aTokenImplementation = await deployGenericATokenImpl(verify); aTokenImplementationAddress = aTokenImplementation.address; rawInsertContractAddressInDb(`aTokenImpl`, aTokenImplementationAddress); - // Deploy delegated aware reserves tokens + const delegatedAwareReserves = Object.entries(reservesParams).filter( ([_, { aTokenImpl }]) => aTokenImpl === eContractid.DelegationAwareAToken ) as [string, IReserveParams][]; @@ -136,122 +130,28 @@ export const initReservesByHelper = async ( rawInsertContractAddressInDb(`delegationAwareATokenImpl`, delegationAwareATokenImplementationAddress); } - // Deploy tokens and rates that uses common aToken in chunks - const reservesChunks = chunk( - Object.entries(reservesParams).filter( - ([_, { aTokenImpl }]) => aTokenImpl === eContractid.AToken - ) as [string, IReserveParams][], - tokensChunks - ); + const reserves = Object.entries(reservesParams).filter( + ([_, { aTokenImpl }]) => aTokenImpl === eContractid.DelegationAwareAToken || + aTokenImpl === eContractid.AToken + ) as [string, IReserveParams][]; - // const reserves = Object.entries(reservesParams).filter( - // ([_, { aTokenImpl }]) => aTokenImpl === eContractid.AToken - // ) as [string, IReserveParams][]; - - - console.log( - `- Token deployments in ${reservesChunks.length * 2} txs instead of ${ - Object.entries(reservesParams).length * 4 - } txs` - ); - // All of these use the same aToken implementation - // but they might use different rate strategy implementations, - // it is better to simply iterate through every reserve instead of chunks later - for (let reservesChunk of reservesChunks) { - - // Prepare data - const tokens: string[] = []; - const symbols: 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 [ - , - { - strategy, - optimalUtilizationRate, - baseVariableBorrowRate, - variableRateSlope1, - variableRateSlope2, - stableRateSlope1, - stableRateSlope2, - }, - ] = (Object.entries(reservesParams) as [string, IReserveParams][])[reserveParamIndex]; - // Add to lists - - tokens.push(tokenAddress); - symbols.push(assetSymbol); - - if (!strategyAddresses[strategy]) { - // Strategy does not exist, create a new one - rateStrategies[strategy] = [ - addressProvider.address, - optimalUtilizationRate, - baseVariableBorrowRate, - variableRateSlope1, - variableRateSlope2, - stableRateSlope1, - stableRateSlope2, - ]; - //lastStrategy = strategy; - strategyAddresses[strategy] = (await deployDefaultReserveInterestRateStrategy( - rateStrategies[strategy], - verify - )).address; - } - strategyAddressPerAsset[assetSymbol] = strategyAddresses[strategy]; - console.log("Strategy address for asset %s: %s", assetSymbol, strategyAddressPerAsset[assetSymbol]) - - reservesDecimals.push(reserveDecimals); - aTokenType[assetSymbol] = "generic"; - // inputParams.push({ - // asset: tokenAddress, - // rates: [ - // optimalUtilizationRate, - // baseVariableBorrowRate, - // variableRateSlope1, - // variableRateSlope2, - // stableRateSlope1, - // stableRateSlope2 - // ] - // }); - } - reserveInitDecimals = [...reserveInitDecimals, ...reservesDecimals]; - reserveTokens = [...reserveTokens, ...tokens]; - reserveSymbols = [...reserveSymbols, ...symbols]; - } - - - - for (let [symbol, params] of delegatedAwareReserves) { - console.log(` - Deploy ${symbol} delegation aware aToken, debts tokens, and strategy`); + for (let [symbol, params] of reserves) { const { strategy, + aTokenImpl, + reserveDecimals, + } = params; + const { optimalUtilizationRate, baseVariableBorrowRate, variableRateSlope1, variableRateSlope2, stableRateSlope1, stableRateSlope2, - } = params; - - if (!strategyAddresses[strategy]) { + } = strategy; + if (!strategyAddresses[strategy.name]) { // Strategy does not exist, create a new one - rateStrategies[strategy] = [ + rateStrategies[strategy.name] = [ addressProvider.address, optimalUtilizationRate, baseVariableBorrowRate, @@ -260,23 +160,28 @@ export const initReservesByHelper = async ( stableRateSlope1, stableRateSlope2, ]; - //lastStrategy = strategy; - strategyAddresses[strategy] = (await deployDefaultReserveInterestRateStrategy( - rateStrategies[strategy], + strategyAddresses[strategy.name] = (await deployDefaultReserveInterestRateStrategy( + rateStrategies[strategy.name], verify )).address; + // This causes the last strategy to be printed twice, once under "DefaultReserveInterestRateStrategy" + // and once under the actual `strategyASSET` key. + rawInsertContractAddressInDb(strategy.name, strategyAddresses[strategy.name]); } - strategyAddressPerAsset[symbol] = strategyAddresses[strategy]; + strategyAddressPerAsset[symbol] = strategyAddresses[strategy.name]; console.log("Strategy address for asset %s: %s", symbol, strategyAddressPerAsset[symbol]) - aTokenType[symbol] = "delegation aware"; - reserveInitDecimals.push(params.reserveDecimals); + if (aTokenImpl === eContractid.AToken) { + aTokenType[symbol] = "generic"; + } else if (aTokenImpl === eContractid.DelegationAwareAToken) { + aTokenType[symbol] = "delegation aware"; + } + + reserveInitDecimals.push(reserveDecimals); reserveTokens.push(tokenAddresses[symbol]); reserveSymbols.push(symbol); } - //gasUsage = gasUsage.add(tx1.gasUsed); - for (let i = 0; i < reserveSymbols.length; i ++) { let aTokenToUse: string; if (aTokenType[reserveSymbols[i]] === 'generic') { @@ -319,7 +224,7 @@ export const initReservesByHelper = async ( console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`); console.log(' * gasUsed', tx3.gasUsed.toString()); - gasUsage = gasUsage.add(tx3.gasUsed); + //gasUsage = gasUsage.add(tx3.gasUsed); } @@ -490,7 +395,7 @@ export const initTokenReservesByHelper = async ( let deployedVariableTokens: string[] = []; let deployedATokens: string[] = []; let deployedRates: string[] = []; - let reserveTokens: string[] = []; + //let reserveTokens: string[] = []; let reserveInitDecimals: string[] = []; let reserveSymbols: string[] = []; @@ -529,10 +434,19 @@ export const initTokenReservesByHelper = async ( console.log(`- Skipping ${symbol} due already initialized`); continue; } - let stableTokenImpl = await getAddressById(`stableDebt${symbol}`, network); - let variableTokenImpl = await getAddressById(`variableDebt${symbol}`, network); - let aTokenImplementation = await getAddressById(`a${symbol}`, network); - let strategyImpl = await getAddressById(`strategy${symbol}`, network); + let stableTokenImpl = await getAddressById(`stableDebtTokenImpl`, network); + let variableTokenImpl = await getAddressById(`variableDebtTokenImpl`, network); + let aTokenImplementation: string | undefined = ""; + const [, { aTokenImpl, strategy }] = (Object.entries(reservesParams) as [string, IReserveParams][])[ + reserveParamIndex + ]; + if (aTokenImpl === eContractid.AToken) { + aTokenImplementation = await getAddressById(`aTokenImpl`, network); + } else if (aTokenImpl === eContractid.DelegationAwareAToken) { + aTokenImplementation = await getAddressById(`delegationAwareATokenImpl`, network); + } + + let strategyImpl = await getAddressById(strategy.name, network); if (!stableTokenImpl) { const stableDebt = await deployStableDebtToken( @@ -582,14 +496,17 @@ export const initTokenReservesByHelper = async ( const [ , { - optimalUtilizationRate, - baseVariableBorrowRate, - variableRateSlope1, - variableRateSlope2, - stableRateSlope1, - stableRateSlope2, + strategy }, ] = (Object.entries(reservesParams) as [string, IReserveParams][])[reserveParamIndex]; + const { + optimalUtilizationRate, + baseVariableBorrowRate, + variableRateSlope1, + variableRateSlope2, + stableRateSlope1, + stableRateSlope2, + } = strategy; const rates = await deployDefaultReserveInterestRateStrategy( [ tokenAddresses[symbol], @@ -604,19 +521,19 @@ export const initTokenReservesByHelper = async ( ); strategyImpl = rates.address; } - const symbols = [`a${symbol}`, `variableDebt${symbol}`, `stableDebt${symbol}`]; - const tokens = [aTokenImplementation, variableTokenImpl, stableTokenImpl]; - for (let index = 0; index < symbols.length; index++) { - if (!(await isErc20SymbolCorrect(tokens[index], symbols[index]))) { - console.error(`${symbol} and implementation does not match: ${tokens[index]}`); - throw Error('Symbol does not match implementation.'); - } - } + // --- REMOVED BECAUSE WE NOW USE THE SAME IMPLEMENTATIONS --- + // const symbols = [`a${symbol}`, `variableDebt${symbol}`, `stableDebt${symbol}`]; + // const tokens = [aTokenImplementation, variableTokenImpl, stableTokenImpl]; + // for (let index = 0; index < symbols.length; index++) { + // if (!(await isErc20SymbolCorrect(tokens[index], symbols[index]))) { + // console.error(`${symbol} and implementation does not match: ${tokens[index]}`); + // throw Error('Symbol does not match implementation.'); + // } + // } console.log(`- Added ${symbol} to the initialize batch`); deployedStableTokens.push(stableTokenImpl); deployedVariableTokens.push(variableTokenImpl); deployedATokens.push(aTokenImplementation); - reserveTokens.push(); deployedRates.push(strategyImpl); reserveInitDecimals.push(decimals.toString()); reserveSymbols.push(symbol); diff --git a/helpers/types.ts b/helpers/types.ts index 4a8b6475..b6c9195f 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -329,16 +329,26 @@ export enum TokenContractId { export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { aTokenImpl: eContractid; reserveFactor: string; - strategy: string; + strategy: IInterestRateStrategyParams; } -export interface IReserveBorrowParams { +export interface IInterestRateStrategyParams { + name: string, optimalUtilizationRate: string; baseVariableBorrowRate: string; variableRateSlope1: string; variableRateSlope2: string; stableRateSlope1: string; stableRateSlope2: string; +} + +export interface IReserveBorrowParams { + // optimalUtilizationRate: string; + // baseVariableBorrowRate: string; + // variableRateSlope1: string; + // variableRateSlope2: string; + // stableRateSlope1: string; + // stableRateSlope2: string; borrowingEnabled: boolean; stableBorrowRateEnabled: boolean; reserveDecimals: string; diff --git a/markets/aave/rateStrategies.ts b/markets/aave/rateStrategies.ts new file mode 100644 index 00000000..afe19b63 --- /dev/null +++ b/markets/aave/rateStrategies.ts @@ -0,0 +1,91 @@ +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(), +} diff --git a/markets/aave/reservesConfigs.ts b/markets/aave/reservesConfigs.ts index 213cb6cf..6921afed 100644 --- a/markets/aave/reservesConfigs.ts +++ b/markets/aave/reservesConfigs.ts @@ -1,15 +1,19 @@ -import BigNumber from 'bignumber.js'; -import { oneRay } from '../../helpers/constants'; +// import BigNumber from 'bignumber.js'; +// import { oneRay } from '../../helpers/constants'; import { eContractid, IReserveParams } from '../../helpers/types'; +import { + rateStrategyStableOne, + rateStrategyStableTwo, + rateStrategyStableThree, + rateStrategyWETH, + rateStrategyAAVE, + rateStrategyVolatileOne, + rateStrategyVolatileTwo, + rateStrategyVolatileThree, +} from './rateStrategies'; export const strategyBUSD: IReserveParams = { - strategy: "busd", - 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', + strategy: rateStrategyStableOne, baseLTVAsCollateral: '0', liquidationThreshold: '0', liquidationBonus: '0', @@ -21,13 +25,7 @@ export const strategyBUSD: IReserveParams = { }; export const strategyDAI: IReserveParams = { - strategy: "dai", - 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(), + strategy: rateStrategyStableTwo, baseLTVAsCollateral: '7500', liquidationThreshold: '8000', liquidationBonus: '10500', @@ -39,13 +37,7 @@ export const strategyDAI: IReserveParams = { }; export const strategySUSD: IReserveParams = { - strategy: "susd", - 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', + strategy: rateStrategyStableOne, baseLTVAsCollateral: '0', liquidationThreshold: '0', liquidationBonus: '0', @@ -57,13 +49,7 @@ export const strategySUSD: IReserveParams = { }; export const strategyTUSD: IReserveParams = { - strategy: "tusd", - 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(), + strategy: rateStrategyStableTwo, baseLTVAsCollateral: '7500', liquidationThreshold: '8000', liquidationBonus: '10500', @@ -75,13 +61,7 @@ export const strategyTUSD: IReserveParams = { }; export const strategyUSDC: IReserveParams = { - strategy: "usdc", - 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(), + strategy: rateStrategyStableThree, baseLTVAsCollateral: '8000', liquidationThreshold: '8500', liquidationBonus: '10500', @@ -93,13 +73,7 @@ export const strategyUSDC: IReserveParams = { }; export const strategyUSDT: IReserveParams = { - strategy: "usdt", - 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(), + strategy: rateStrategyStableThree, baseLTVAsCollateral: '8000', liquidationThreshold: '8500', liquidationBonus: '10500', @@ -111,13 +85,7 @@ export const strategyUSDT: IReserveParams = { }; export const strategyAAVE: IReserveParams = { - strategy: "aave", - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyAAVE, baseLTVAsCollateral: '5000', liquidationThreshold: '6500', liquidationBonus: '11000', @@ -129,13 +97,7 @@ export const strategyAAVE: IReserveParams = { }; export const strategyBAT: IReserveParams = { - strategy: "bat", - 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(), + strategy: rateStrategyVolatileOne, baseLTVAsCollateral: '7000', liquidationThreshold: '7500', liquidationBonus: '11000', @@ -147,13 +109,7 @@ export const strategyBAT: IReserveParams = { }; export const strategyENJ: IReserveParams = { - strategy: "enj", - 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(), + strategy: rateStrategyVolatileOne, baseLTVAsCollateral: '5500', liquidationThreshold: '6000', liquidationBonus: '11000', @@ -165,13 +121,7 @@ export const strategyENJ: IReserveParams = { }; export const strategyWETH: IReserveParams = { - strategy: "weth", - 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(), + strategy: rateStrategyWETH, baseLTVAsCollateral: '8000', liquidationThreshold: '8250', liquidationBonus: '10500', @@ -183,13 +133,7 @@ export const strategyWETH: IReserveParams = { }; export const strategyKNC: IReserveParams = { - strategy: "knc", - 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(), + strategy: rateStrategyVolatileTwo, baseLTVAsCollateral: '6000', liquidationThreshold: '6500', liquidationBonus: '11000', @@ -201,13 +145,7 @@ export const strategyKNC: IReserveParams = { }; export const strategyLINK: IReserveParams = { - strategy: "link", - 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(), + strategy: rateStrategyVolatileOne, baseLTVAsCollateral: '7000', liquidationThreshold: '7500', liquidationBonus: '11000', @@ -219,13 +157,7 @@ export const strategyLINK: IReserveParams = { }; export const strategyMANA: IReserveParams = { - strategy: "mana", - 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(), + strategy: rateStrategyVolatileOne, baseLTVAsCollateral: '6000', liquidationThreshold: '6500', liquidationBonus: '11000', @@ -237,13 +169,7 @@ export const strategyMANA: IReserveParams = { }; export const strategyMKR: IReserveParams = { - strategy: "mkr", - 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(), + strategy: rateStrategyVolatileOne, baseLTVAsCollateral: '6000', liquidationThreshold: '6500', liquidationBonus: '11000', @@ -255,13 +181,7 @@ export const strategyMKR: IReserveParams = { }; export const strategyREN: IReserveParams = { - strategy: "ren", - 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(), + strategy: rateStrategyVolatileOne, baseLTVAsCollateral: '5500', liquidationThreshold: '6000', liquidationBonus: '11000', @@ -273,13 +193,7 @@ export const strategyREN: IReserveParams = { }; export const strategySNX: IReserveParams = { - strategy: "snx", - optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.12).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyVolatileThree, baseLTVAsCollateral: '1500', liquidationThreshold: '4000', liquidationBonus: '11000', @@ -290,14 +204,9 @@ export const strategySNX: IReserveParams = { reserveFactor: '3500' }; +// Invalid borrow rates in params currently, replaced with snx params export const strategyUNI: IReserveParams = { - strategy: "uni", - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - variableRateSlope1: '0', - variableRateSlope2: '0', - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyVolatileThree, baseLTVAsCollateral: '6000', liquidationThreshold: '6500', liquidationBonus: '11000', @@ -309,13 +218,7 @@ export const strategyUNI: IReserveParams = { }; export const strategyWBTC: IReserveParams = { - strategy: "wbtc", - optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: '0', - 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(), + strategy: rateStrategyVolatileTwo, baseLTVAsCollateral: '7000', liquidationThreshold: '7500', liquidationBonus: '11000', @@ -327,13 +230,7 @@ export const strategyWBTC: IReserveParams = { }; export const strategyYFI: IReserveParams = { - strategy: "yfi", - 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: new BigNumber(0.1).multipliedBy(oneRay).toFixed(), - stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(), + strategy: rateStrategyVolatileOne, baseLTVAsCollateral: '4000', liquidationThreshold: '5500', liquidationBonus: '11500', @@ -345,13 +242,7 @@ export const strategyYFI: IReserveParams = { }; export const strategyZRX: IReserveParams = { - strategy: "zrx", - 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: new BigNumber(0.1).multipliedBy(oneRay).toFixed(), - stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(), + strategy: rateStrategyVolatileOne, baseLTVAsCollateral: '6000', liquidationThreshold: '6500', liquidationBonus: '11000', diff --git a/markets/lp/rateStrategies.ts b/markets/lp/rateStrategies.ts new file mode 100644 index 00000000..a91af2ea --- /dev/null +++ b/markets/lp/rateStrategies.ts @@ -0,0 +1,36 @@ +import BigNumber from 'bignumber.js'; +import { oneRay } from '../../helpers/constants'; +import { IInterestRateStrategyParams } from '../../helpers/types'; + +// DAIWETH WBTCWETH AAVEWETH BATWETH USDCDAI CRVWETH LINKWETH MKRWETH RENWETH SNXWETH UNIWETH USDCWETH WBTCUSDC YFIWETH +export const rateStrategyLpBase: IInterestRateStrategyParams = { + name: "rateStrategyLpBase", + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), + stableRateSlope1: '0', + stableRateSlope2: '0', +} + +// WETH WBTC +export const rateStrategyBaseOne: IInterestRateStrategyParams = { + name: "rateStrategyBaseOne", + 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(), +} + +// DAI USDC USDT +export const rateStrategyStable: IInterestRateStrategyParams = { + name: "rateStrategyStable", + 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.60).multipliedBy(oneRay).toFixed(), +} \ No newline at end of file diff --git a/markets/lp/reservesConfigs.ts b/markets/lp/reservesConfigs.ts index a27261d0..21db2a1e 100644 --- a/markets/lp/reservesConfigs.ts +++ b/markets/lp/reservesConfigs.ts @@ -1,15 +1,13 @@ -import BigNumber from 'bignumber.js'; -import { oneRay } from '../../helpers/constants'; -import { eContractid, IReserveParams } from '../../helpers/types'; +import { eContractid, IReserveParams} from '../../helpers/types'; +import { + rateStrategyLpBase, + rateStrategyStable, + rateStrategyBaseOne, +} from './rateStrategies'; + export const strategyWETH: IReserveParams = { - strategy: 'WETH and WBTC', - 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(), + strategy: rateStrategyBaseOne, baseLTVAsCollateral: '8000', liquidationThreshold: '8250', liquidationBonus: '10500', @@ -21,13 +19,7 @@ export const strategyWETH: IReserveParams = { }; export const strategyWBTC: IReserveParams = { - strategy: 'WETH and WBTC', - 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(), + strategy: rateStrategyBaseOne, baseLTVAsCollateral: '7000', liquidationThreshold: '7500', liquidationBonus: '11000', @@ -39,13 +31,7 @@ export const strategyWBTC: IReserveParams = { }; export const strategyDAI: IReserveParams = { - strategy: 'stablecoin', - 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.60).multipliedBy(oneRay).toFixed(), + strategy: rateStrategyStable, baseLTVAsCollateral: '7500', liquidationThreshold: '8000', liquidationBonus: '10500', @@ -57,13 +43,7 @@ export const strategyDAI: IReserveParams = { }; export const strategyUSDC: IReserveParams = { - strategy: 'stablecoin', - 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.60).multipliedBy(oneRay).toFixed(), + strategy: rateStrategyStable, baseLTVAsCollateral: '8000', liquidationThreshold: '8500', liquidationBonus: '10500', @@ -75,13 +55,7 @@ export const strategyUSDC: IReserveParams = { }; export const strategyUSDT: IReserveParams = { - strategy: 'stablecoin', - 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.60).multipliedBy(oneRay).toFixed(), + strategy: rateStrategyStable, baseLTVAsCollateral: '-1', liquidationThreshold: '8500', liquidationBonus: '10500', @@ -93,13 +67,7 @@ export const strategyUSDT: IReserveParams = { }; export const strategyDAIWETH: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -111,13 +79,7 @@ export const strategyDAIWETH: IReserveParams = { }; export const strategyWBTCWETH: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -129,13 +91,7 @@ export const strategyWBTCWETH: IReserveParams = { }; export const strategyAAVEWETH: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -147,13 +103,7 @@ export const strategyAAVEWETH: IReserveParams = { }; export const strategyBATWETH: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -165,13 +115,7 @@ export const strategyBATWETH: IReserveParams = { }; export const strategyUSDCDAI: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -183,13 +127,7 @@ export const strategyUSDCDAI: IReserveParams = { }; export const strategyCRVWETH: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '5000', liquidationThreshold: '6000', liquidationBonus: '11500', @@ -201,13 +139,7 @@ export const strategyCRVWETH: IReserveParams = { }; export const strategyLINKWETH: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -219,13 +151,7 @@ export const strategyLINKWETH: IReserveParams = { }; export const strategyMKRWETH: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -237,13 +163,7 @@ export const strategyMKRWETH: IReserveParams = { }; export const strategyRENWETH: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -255,13 +175,7 @@ export const strategyRENWETH: IReserveParams = { }; export const strategySNXWETH: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '4000', liquidationThreshold: '6000', liquidationBonus: '11500', @@ -273,13 +187,7 @@ export const strategySNXWETH: IReserveParams = { }; export const strategyUNIWETH: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -291,13 +199,7 @@ export const strategyUNIWETH: IReserveParams = { }; export const strategyUSDCWETH: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -309,13 +211,7 @@ export const strategyUSDCWETH: IReserveParams = { }; export const strategyWBTCUSDC: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -327,13 +223,7 @@ export const strategyWBTCUSDC: IReserveParams = { }; export const strategyYFIWETH: IReserveParams = { - strategy: 'uniswap LP base', - optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), - baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), - variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), - variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + strategy: rateStrategyLpBase, baseLTVAsCollateral: '5000', liquidationThreshold: '6000', liquidationBonus: '11500', diff --git a/tasks/verifications/2_tokens.ts b/tasks/verifications/2_tokens.ts index 591aa45a..4ea86cc5 100644 --- a/tasks/verifications/2_tokens.ts +++ b/tasks/verifications/2_tokens.ts @@ -52,7 +52,7 @@ task('verify:tokens', 'Deploy oracles for dev enviroment') variableRateSlope2, stableRateSlope1, stableRateSlope2, - } = tokenConfig[1]; + } = tokenConfig[1].strategy; console.log; // Proxy Stable Debt From d131afb6a0651bae39575299266e88c0158b357e Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 10 Feb 2021 18:23:20 -0500 Subject: [PATCH 090/219] Fixed test suites to work with new deployment functionality --- .../test-aave/helpers/utils/calculations.ts | 19 ++++++++++--------- .../test-lp/helpers/utils/calculations.ts | 18 +++++++++--------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/test-suites/test-aave/helpers/utils/calculations.ts b/test-suites/test-aave/helpers/utils/calculations.ts index fd6dea53..de3d31f9 100644 --- a/test-suites/test-aave/helpers/utils/calculations.ts +++ b/test-suites/test-aave/helpers/utils/calculations.ts @@ -8,6 +8,7 @@ import { } from '../../../../helpers/types'; import './math'; import { ReserveData, UserReserveData } from './interfaces'; +import { expect } from 'chai'; export const strToBN = (amount: string): BigNumber => new BigNumber(amount); @@ -1243,29 +1244,29 @@ export const calcExpectedInterestRates = ( ]; let stableBorrowRate: BigNumber = marketStableRate; - let variableBorrowRate: BigNumber = new BigNumber(reserveConfiguration.baseVariableBorrowRate); + let variableBorrowRate: BigNumber = new BigNumber(reserveConfiguration.strategy.baseVariableBorrowRate); - const optimalRate = new BigNumber(reserveConfiguration.optimalUtilizationRate); + const optimalRate = new BigNumber(reserveConfiguration.strategy.optimalUtilizationRate); const excessRate = new BigNumber(RAY).minus(optimalRate); if (utilizationRate.gt(optimalRate)) { const excessUtilizationRateRatio = utilizationRate - .minus(reserveConfiguration.optimalUtilizationRate) + .minus(reserveConfiguration.strategy.optimalUtilizationRate) .rayDiv(excessRate); stableBorrowRate = stableBorrowRate - .plus(reserveConfiguration.stableRateSlope1) + .plus(reserveConfiguration.strategy.stableRateSlope1) .plus( - new BigNumber(reserveConfiguration.stableRateSlope2).rayMul(excessUtilizationRateRatio) + new BigNumber(reserveConfiguration.strategy.stableRateSlope2).rayMul(excessUtilizationRateRatio) ); variableBorrowRate = variableBorrowRate - .plus(reserveConfiguration.variableRateSlope1) + .plus(reserveConfiguration.strategy.variableRateSlope1) .plus( - new BigNumber(reserveConfiguration.variableRateSlope2).rayMul(excessUtilizationRateRatio) + new BigNumber(reserveConfiguration.strategy.variableRateSlope2).rayMul(excessUtilizationRateRatio) ); } else { stableBorrowRate = stableBorrowRate.plus( - new BigNumber(reserveConfiguration.stableRateSlope1).rayMul( + new BigNumber(reserveConfiguration.strategy.stableRateSlope1).rayMul( utilizationRate.rayDiv(new BigNumber(optimalRate)) ) ); @@ -1273,7 +1274,7 @@ export const calcExpectedInterestRates = ( variableBorrowRate = variableBorrowRate.plus( utilizationRate .rayDiv(optimalRate) - .rayMul(new BigNumber(reserveConfiguration.variableRateSlope1)) + .rayMul(new BigNumber(reserveConfiguration.strategy.variableRateSlope1)) ); } diff --git a/test-suites/test-lp/helpers/utils/calculations.ts b/test-suites/test-lp/helpers/utils/calculations.ts index 317645f2..1a801cc1 100644 --- a/test-suites/test-lp/helpers/utils/calculations.ts +++ b/test-suites/test-lp/helpers/utils/calculations.ts @@ -1247,29 +1247,29 @@ export const calcExpectedInterestRates = ( ]; let stableBorrowRate: BigNumber = marketStableRate; - let variableBorrowRate: BigNumber = new BigNumber(reserveConfiguration.baseVariableBorrowRate); + let variableBorrowRate: BigNumber = new BigNumber(reserveConfiguration.strategy.baseVariableBorrowRate); - const optimalRate = new BigNumber(reserveConfiguration.optimalUtilizationRate); + const optimalRate = new BigNumber(reserveConfiguration.strategy.optimalUtilizationRate); const excessRate = new BigNumber(RAY).minus(optimalRate); if (utilizationRate.gt(optimalRate)) { const excessUtilizationRateRatio = utilizationRate - .minus(reserveConfiguration.optimalUtilizationRate) + .minus(reserveConfiguration.strategy.optimalUtilizationRate) .rayDiv(excessRate); stableBorrowRate = stableBorrowRate - .plus(reserveConfiguration.stableRateSlope1) + .plus(reserveConfiguration.strategy.stableRateSlope1) .plus( - new BigNumber(reserveConfiguration.stableRateSlope2).rayMul(excessUtilizationRateRatio) + new BigNumber(reserveConfiguration.strategy.stableRateSlope2).rayMul(excessUtilizationRateRatio) ); variableBorrowRate = variableBorrowRate - .plus(reserveConfiguration.variableRateSlope1) + .plus(reserveConfiguration.strategy.variableRateSlope1) .plus( - new BigNumber(reserveConfiguration.variableRateSlope2).rayMul(excessUtilizationRateRatio) + new BigNumber(reserveConfiguration.strategy.variableRateSlope2).rayMul(excessUtilizationRateRatio) ); } else { stableBorrowRate = stableBorrowRate.plus( - new BigNumber(reserveConfiguration.stableRateSlope1).rayMul( + new BigNumber(reserveConfiguration.strategy.stableRateSlope1).rayMul( utilizationRate.rayDiv(new BigNumber(optimalRate)) ) ); @@ -1277,7 +1277,7 @@ export const calcExpectedInterestRates = ( variableBorrowRate = variableBorrowRate.plus( utilizationRate .rayDiv(optimalRate) - .rayMul(new BigNumber(reserveConfiguration.variableRateSlope1)) + .rayMul(new BigNumber(reserveConfiguration.strategy.variableRateSlope1)) ); } From 5fe4603e3de122e4e0304e0b44c6a1c4924f88b6 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 10 Feb 2021 18:23:30 -0500 Subject: [PATCH 091/219] Fixed deprecated /test/ test suite --- test/helpers/utils/calculations.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/helpers/utils/calculations.ts b/test/helpers/utils/calculations.ts index a4db008f..aeb9d74e 100644 --- a/test/helpers/utils/calculations.ts +++ b/test/helpers/utils/calculations.ts @@ -1243,29 +1243,29 @@ export const calcExpectedInterestRates = ( ]; let stableBorrowRate: BigNumber = marketStableRate; - let variableBorrowRate: BigNumber = new BigNumber(reserveConfiguration.baseVariableBorrowRate); + let variableBorrowRate: BigNumber = new BigNumber(reserveConfiguration.strategy.baseVariableBorrowRate); - const optimalRate = new BigNumber(reserveConfiguration.optimalUtilizationRate); + const optimalRate = new BigNumber(reserveConfiguration.strategy.optimalUtilizationRate); const excessRate = new BigNumber(RAY).minus(optimalRate); if (utilizationRate.gt(optimalRate)) { const excessUtilizationRateRatio = utilizationRate - .minus(reserveConfiguration.optimalUtilizationRate) + .minus(reserveConfiguration.strategy.optimalUtilizationRate) .rayDiv(excessRate); stableBorrowRate = stableBorrowRate - .plus(reserveConfiguration.stableRateSlope1) + .plus(reserveConfiguration.strategy.stableRateSlope1) .plus( - new BigNumber(reserveConfiguration.stableRateSlope2).rayMul(excessUtilizationRateRatio) + new BigNumber(reserveConfiguration.strategy.stableRateSlope2).rayMul(excessUtilizationRateRatio) ); variableBorrowRate = variableBorrowRate - .plus(reserveConfiguration.variableRateSlope1) + .plus(reserveConfiguration.strategy.variableRateSlope1) .plus( - new BigNumber(reserveConfiguration.variableRateSlope2).rayMul(excessUtilizationRateRatio) + new BigNumber(reserveConfiguration.strategy.variableRateSlope2).rayMul(excessUtilizationRateRatio) ); } else { stableBorrowRate = stableBorrowRate.plus( - new BigNumber(reserveConfiguration.stableRateSlope1).rayMul( + new BigNumber(reserveConfiguration.strategy.stableRateSlope1).rayMul( utilizationRate.rayDiv(new BigNumber(optimalRate)) ) ); @@ -1273,7 +1273,7 @@ export const calcExpectedInterestRates = ( variableBorrowRate = variableBorrowRate.plus( utilizationRate .rayDiv(optimalRate) - .rayMul(new BigNumber(reserveConfiguration.variableRateSlope1)) + .rayMul(new BigNumber(reserveConfiguration.strategy.variableRateSlope1)) ); } From 9fb097e687ba760022ec116d1d9a0da50912a1c8 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 10 Feb 2021 18:36:51 -0500 Subject: [PATCH 092/219] Removed old console lo --- tasks/full/5_initialize.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 438e3519..813a6a3e 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -45,7 +45,7 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') } const treasuryAddress = await getTreasuryAddress(poolConfig); - console.log("here"); + await initReservesByHelper( ReservesConfig, reserveAssets, From 0a3da08c9cd411528753e91de6057fc6501017bc Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 10 Feb 2021 18:47:31 -0500 Subject: [PATCH 093/219] Added a few comments for clarity --- helpers/init-helpers.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index de0e99f4..4664bb23 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -230,7 +230,7 @@ export const initReservesByHelper = async ( // Set deployer back as admin await waitForTx(await addressProvider.setPoolAdmin(admin)); - return gasUsage; + return gasUsage; // Deprecated }; export const getPairsTokenAggregator = ( @@ -578,9 +578,10 @@ export const initTokenReservesByHelper = async ( // Set deployer back as admin await waitForTx(await addressProvider.setPoolAdmin(admin)); - return gasUsage; + return gasUsage; // No longer relevant }; +// Function deprecated const isErc20SymbolCorrect = async (token: tEthereumAddress, symbol: string) => { const erc20 = await getAToken(token); // using aToken for ERC20 interface const erc20Symbol = await erc20.symbol(); From 4080bb5983d111e077bf4cf93df14f0caf1bb6d1 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 10 Feb 2021 18:52:06 -0500 Subject: [PATCH 094/219] Removed deprecated /test/ test directory --- test/__setup.spec.ts | 292 --- test/addresses-provider-registry.spec.ts | 100 - test/atoken-modifiers.spec.ts | 35 - test/atoken-permit.spec.ts | 312 --- test/atoken-transfer.spec.ts | 99 - test/configurator.spec.ts | 386 ---- test/delegation-aware-atoken.spec.ts | 64 - test/flashloan.spec.ts | 497 ----- test/helpers/actions.ts | 772 ------- test/helpers/almost-equal.ts | 31 - test/helpers/make-suite.ts | 191 -- test/helpers/scenario-engine.ts | 237 --- test/helpers/scenarios/borrow-negatives.json | 142 -- .../scenarios/borrow-repay-stable.json | 656 ------ .../scenarios/borrow-repay-variable.json | 945 --------- test/helpers/scenarios/credit-delegation.json | 157 -- test/helpers/scenarios/deposit.json | 266 --- .../scenarios/rebalance-stable-rate.json | 198 -- .../scenarios/set-use-as-collateral.json | 236 --- test/helpers/scenarios/swap-rate-mode.json | 167 -- .../helpers/scenarios/withdraw-negatives.json | 114 - test/helpers/scenarios/withdraw.json | 340 --- test/helpers/utils/calculations.ts | 1434 ------------- test/helpers/utils/helpers.ts | 128 -- test/helpers/utils/interfaces/index.ts | 40 - test/helpers/utils/math.ts | 97 - test/lending-pool-addresses-provider.spec.ts | 101 - test/liquidation-atoken.spec.ts | 379 ---- test/liquidation-underlying.spec.ts | 492 ----- test/mainnet/check-list.spec.ts | 366 ---- test/pausable-functions.spec.ts | 330 --- test/pool-modifiers.spec.ts | 241 --- test/rate-strategy.spec.ts | 165 -- test/scenario.spec.ts | 44 - test/stable-rate-economy.spec.ts | 199 -- test/stable-token.spec.ts | 37 - test/subgraph-scenarios.spec.ts | 32 - test/uniswapAdapters.base.spec.ts | 227 -- test/uniswapAdapters.flashLiquidation.spec.ts | 850 -------- test/uniswapAdapters.liquiditySwap.spec.ts | 1854 ----------------- test/uniswapAdapters.repay.spec.ts | 1469 ------------- test/upgradeability.spec.ts | 234 --- test/variable-debt-token.spec.ts | 36 - test/weth-gateway.spec.ts | 370 ---- 44 files changed, 15362 deletions(-) delete mode 100644 test/__setup.spec.ts delete mode 100644 test/addresses-provider-registry.spec.ts delete mode 100644 test/atoken-modifiers.spec.ts delete mode 100644 test/atoken-permit.spec.ts delete mode 100644 test/atoken-transfer.spec.ts delete mode 100644 test/configurator.spec.ts delete mode 100644 test/delegation-aware-atoken.spec.ts delete mode 100644 test/flashloan.spec.ts delete mode 100644 test/helpers/actions.ts delete mode 100644 test/helpers/almost-equal.ts delete mode 100644 test/helpers/make-suite.ts delete mode 100644 test/helpers/scenario-engine.ts delete mode 100644 test/helpers/scenarios/borrow-negatives.json delete mode 100644 test/helpers/scenarios/borrow-repay-stable.json delete mode 100644 test/helpers/scenarios/borrow-repay-variable.json delete mode 100644 test/helpers/scenarios/credit-delegation.json delete mode 100644 test/helpers/scenarios/deposit.json delete mode 100644 test/helpers/scenarios/rebalance-stable-rate.json delete mode 100644 test/helpers/scenarios/set-use-as-collateral.json delete mode 100644 test/helpers/scenarios/swap-rate-mode.json delete mode 100644 test/helpers/scenarios/withdraw-negatives.json delete mode 100644 test/helpers/scenarios/withdraw.json delete mode 100644 test/helpers/utils/calculations.ts delete mode 100644 test/helpers/utils/helpers.ts delete mode 100644 test/helpers/utils/interfaces/index.ts delete mode 100644 test/helpers/utils/math.ts delete mode 100644 test/lending-pool-addresses-provider.spec.ts delete mode 100644 test/liquidation-atoken.spec.ts delete mode 100644 test/liquidation-underlying.spec.ts delete mode 100644 test/mainnet/check-list.spec.ts delete mode 100644 test/pausable-functions.spec.ts delete mode 100644 test/pool-modifiers.spec.ts delete mode 100644 test/rate-strategy.spec.ts delete mode 100644 test/scenario.spec.ts delete mode 100644 test/stable-rate-economy.spec.ts delete mode 100644 test/stable-token.spec.ts delete mode 100644 test/subgraph-scenarios.spec.ts delete mode 100644 test/uniswapAdapters.base.spec.ts delete mode 100644 test/uniswapAdapters.flashLiquidation.spec.ts delete mode 100644 test/uniswapAdapters.liquiditySwap.spec.ts delete mode 100644 test/uniswapAdapters.repay.spec.ts delete mode 100644 test/upgradeability.spec.ts delete mode 100644 test/variable-debt-token.spec.ts delete mode 100644 test/weth-gateway.spec.ts diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts deleted file mode 100644 index c9be6515..00000000 --- a/test/__setup.spec.ts +++ /dev/null @@ -1,292 +0,0 @@ -import rawBRE from 'hardhat'; -import { MockContract } from 'ethereum-waffle'; -import { - insertContractAddressInDb, - getEthersSigners, - registerContractInJsonDb, -} from '../helpers/contracts-helpers'; -import { - deployLendingPoolAddressesProvider, - deployMintableERC20, - deployLendingPoolAddressesProviderRegistry, - deployLendingPoolConfigurator, - deployLendingPool, - deployPriceOracle, - deployAaveOracle, - deployLendingPoolCollateralManager, - deployMockFlashLoanReceiver, - deployWalletBalancerProvider, - deployAaveProtocolDataProvider, - deployLendingRateOracle, - deployStableAndVariableTokensHelper, - deployATokensAndRatesHelper, - deployWETHGateway, - deployWETHMocked, - deployMockUniswapRouter, - deployUniswapLiquiditySwapAdapter, - deployUniswapRepayAdapter, - deployFlashLiquidationAdapter, -} from '../helpers/contracts-deployments'; -import { Signer } from 'ethers'; -import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../helpers/types'; -import { MintableERC20 } from '../types/MintableERC20'; -import { - ConfigNames, - getReservesConfigByPool, - getTreasuryAddress, - loadPoolConfig, -} from '../helpers/configuration'; -import { initializeMakeSuite } from './helpers/make-suite'; - -import { - setInitialAssetPricesInOracle, - deployAllMockAggregators, - setInitialMarketRatesInRatesOracleByHelper, -} from '../helpers/oracles-helpers'; -import { DRE, waitForTx } from '../helpers/misc-utils'; -import { initReservesByHelper, configureReservesByHelper } from '../helpers/init-helpers'; -import AaveConfig from '../markets/aave'; -import { ZERO_ADDRESS } from '../helpers/constants'; -import { - getLendingPool, - getLendingPoolConfiguratorProxy, - getPairsTokenAggregator, -} from '../helpers/contracts-getters'; -import { WETH9Mocked } from '../types/WETH9Mocked'; - -const MOCK_USD_PRICE_IN_WEI = AaveConfig.ProtocolGlobalParams.MockUsdPriceInWei; -const ALL_ASSETS_INITIAL_PRICES = AaveConfig.Mocks.AllAssetsInitialPrices; -const USD_ADDRESS = AaveConfig.ProtocolGlobalParams.UsdAddress; -const MOCK_CHAINLINK_AGGREGATORS_PRICES = AaveConfig.Mocks.AllAssetsInitialPrices; -const LENDING_RATE_ORACLE_RATES_COMMON = AaveConfig.LendingRateOracleRatesCommon; - -const deployAllMockTokens = async (deployer: Signer) => { - const tokens: { [symbol: string]: MockContract | MintableERC20 | WETH9Mocked } = {}; - - const protoConfigData = getReservesConfigByPool(AavePools.proto); - - for (const tokenSymbol of Object.keys(TokenContractId)) { - if (tokenSymbol === 'WETH') { - tokens[tokenSymbol] = await deployWETHMocked(); - await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); - continue; - } - let decimals = 18; - - let configData = (protoConfigData)[tokenSymbol]; - - if (!configData) { - decimals = 18; - } - - tokens[tokenSymbol] = await deployMintableERC20([ - tokenSymbol, - tokenSymbol, - configData ? configData.reserveDecimals : 18, - ]); - await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); - } - - return tokens; -}; - -const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { - console.time('setup'); - const aaveAdmin = await deployer.getAddress(); - - const mockTokens = await deployAllMockTokens(deployer); - - const addressesProvider = await deployLendingPoolAddressesProvider(AaveConfig.MarketId); - await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin)); - - //setting users[1] as emergency admin, which is in position 2 in the DRE addresses list - const addressList = await Promise.all( - (await DRE.ethers.getSigners()).map((signer) => signer.getAddress()) - ); - - await waitForTx(await addressesProvider.setEmergencyAdmin(addressList[2])); - - const addressesProviderRegistry = await deployLendingPoolAddressesProviderRegistry(); - await waitForTx( - await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 1) - ); - - const lendingPoolImpl = await deployLendingPool(); - - await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address)); - - const lendingPoolAddress = await addressesProvider.getLendingPool(); - const lendingPoolProxy = await getLendingPool(lendingPoolAddress); - - await insertContractAddressInDb(eContractid.LendingPool, lendingPoolProxy.address); - - const lendingPoolConfiguratorImpl = await deployLendingPoolConfigurator(); - await waitForTx( - await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImpl.address) - ); - const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy( - await addressesProvider.getLendingPoolConfigurator() - ); - await insertContractAddressInDb( - eContractid.LendingPoolConfigurator, - 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( - ALL_ASSETS_INITIAL_PRICES, - { - WETH: mockTokens.WETH.address, - DAI: mockTokens.DAI.address, - TUSD: mockTokens.TUSD.address, - USDC: mockTokens.USDC.address, - USDT: mockTokens.USDT.address, - SUSD: mockTokens.SUSD.address, - AAVE: mockTokens.AAVE.address, - BAT: mockTokens.BAT.address, - MKR: mockTokens.MKR.address, - LINK: mockTokens.LINK.address, - KNC: mockTokens.KNC.address, - WBTC: mockTokens.WBTC.address, - MANA: mockTokens.MANA.address, - ZRX: mockTokens.ZRX.address, - SNX: mockTokens.SNX.address, - BUSD: mockTokens.BUSD.address, - YFI: mockTokens.BUSD.address, - REN: mockTokens.REN.address, - UNI: mockTokens.UNI.address, - ENJ: mockTokens.ENJ.address, - LpDAI: mockTokens.LpDAI.address, - LpUSDC: mockTokens.LpUSDC.address, - LpUSDT: mockTokens.LpUSDT.address, - LpWBTC: mockTokens.LpWBTC.address, - LpWETH: mockTokens.LpWETH.address, - LpDAIWETH: mockTokens.LpDAIWETH.address, - LpWBTCWETH: mockTokens.LpWBTCWETH.address, - LpAAVEWETH: mockTokens.LpAAVEWETH.address, - LpBATWETH: mockTokens.LpBATWETH.address, - LpUSDCDAI: mockTokens.LpUSDCDAI.address, - LpCRVWETH: mockTokens.LpCRVWETH.address, - LpLINKWETH: mockTokens.LpLINKWETH.address, - LpMKRWETH: mockTokens.LpMKRWETH.address, - LpRENWETH: mockTokens.LpRENWETH.address, - LpSNXWETH: mockTokens.LpSNXWETH.address, - LpUNIWETH: mockTokens.LpUNIWETH.address, - LpUSDCWETH: mockTokens.LpUSDCWETH.address, - LpWBTCUSDC: mockTokens.LpWBTCUSDC.address, - LpYFIWETH: mockTokens.LpYFIWETH.address, - USD: USD_ADDRESS, - }, - fallbackOracle - ); - - const mockAggregators = await deployAllMockAggregators(MOCK_CHAINLINK_AGGREGATORS_PRICES); - - const allTokenAddresses = Object.entries(mockTokens).reduce( - (accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, tokenContract]) => ({ - ...accum, - [tokenSymbol]: tokenContract.address, - }), - {} - ); - const allAggregatorsAddresses = Object.entries(mockAggregators).reduce( - (accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, aggregator]) => ({ - ...accum, - [tokenSymbol]: aggregator.address, - }), - {} - ); - - const [tokens, aggregators] = getPairsTokenAggregator(allTokenAddresses, allAggregatorsAddresses); - - await deployAaveOracle([tokens, aggregators, fallbackOracle.address, mockTokens.WETH.address]); - await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address)); - - const lendingRateOracle = await deployLendingRateOracle(); - await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); - - const { USD, ...tokensAddressesWithoutUsd } = allTokenAddresses; - const allReservesAddresses = { - ...tokensAddressesWithoutUsd, - }; - await setInitialMarketRatesInRatesOracleByHelper( - LENDING_RATE_ORACLE_RATES_COMMON, - allReservesAddresses, - lendingRateOracle, - aaveAdmin - ); - - const reservesParams = getReservesConfigByPool(AavePools.proto); - - const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address); - - await insertContractAddressInDb(eContractid.AaveProtocolDataProvider, testHelpers.address); - const admin = await deployer.getAddress(); - - console.log('Initialize configuration'); - - const config = loadPoolConfig(ConfigNames.Aave); - - const treasuryAddress = await getTreasuryAddress(config); - - await initReservesByHelper( - reservesParams, - allReservesAddresses, - admin, - treasuryAddress, - ZERO_ADDRESS, - false - ); - await configureReservesByHelper(reservesParams, allReservesAddresses, testHelpers, admin); - - const collateralManager = await deployLendingPoolCollateralManager(); - await waitForTx( - await addressesProvider.setLendingPoolCollateralManager(collateralManager.address) - ); - await deployMockFlashLoanReceiver(addressesProvider.address); - - const mockUniswapRouter = await deployMockUniswapRouter(); - - const adapterParams: [string, string, string] = [ - addressesProvider.address, - mockUniswapRouter.address, - mockTokens.WETH.address, - ]; - - await deployUniswapLiquiditySwapAdapter(adapterParams); - await deployUniswapRepayAdapter(adapterParams); - await deployFlashLiquidationAdapter(adapterParams); - - await deployWalletBalancerProvider(); - - await deployWETHGateway([mockTokens.WETH.address, lendingPoolAddress]); - - console.timeEnd('setup'); -}; - -before(async () => { - await rawBRE.run('set-DRE'); - const [deployer, secondaryWallet] = await getEthersSigners(); - const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; - - if (MAINNET_FORK) { - await rawBRE.run('aave:mainnet'); - } else { - console.log('-> Deploying test environment...'); - await buildTestEnv(deployer, secondaryWallet); - } - - await initializeMakeSuite(); - console.log('\n***************'); - console.log('Setup and snapshot finished'); - console.log('***************\n'); -}); diff --git a/test/addresses-provider-registry.spec.ts b/test/addresses-provider-registry.spec.ts deleted file mode 100644 index 5ded1413..00000000 --- a/test/addresses-provider-registry.spec.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { TestEnv, makeSuite } from './helpers/make-suite'; -import { ZERO_ADDRESS } from '../helpers/constants'; -import { ProtocolErrors } from '../helpers/types'; - -const { expect } = require('chai'); - -makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => { - it('Checks the addresses provider is added to the registry', async () => { - const { addressesProvider, registry } = testEnv; - - const providers = await registry.getAddressesProvidersList(); - - expect(providers.length).to.be.equal(1, 'Invalid length of the addresses providers list'); - expect(providers[0].toString()).to.be.equal( - addressesProvider.address, - ' Invalid addresses provider added to the list' - ); - }); - - it('tries to register an addresses provider with id 0', async () => { - const { users, registry } = testEnv; - const { LPAPR_INVALID_ADDRESSES_PROVIDER_ID } = ProtocolErrors; - - await expect(registry.registerAddressesProvider(users[2].address, '0')).to.be.revertedWith( - LPAPR_INVALID_ADDRESSES_PROVIDER_ID - ); - }); - - it('Registers a new mock addresses provider', async () => { - const { users, registry } = testEnv; - - //simulating an addresses provider using the users[1] wallet address - await registry.registerAddressesProvider(users[1].address, '2'); - - const providers = await registry.getAddressesProvidersList(); - - expect(providers.length).to.be.equal(2, 'Invalid length of the addresses providers list'); - expect(providers[1].toString()).to.be.equal( - users[1].address, - ' Invalid addresses provider added to the list' - ); - }); - - it('Removes the mock addresses provider', async () => { - const { users, registry, addressesProvider } = testEnv; - - const id = await registry.getAddressesProviderIdByAddress(users[1].address); - - expect(id).to.be.equal('2', 'Invalid isRegistered return value'); - - await registry.unregisterAddressesProvider(users[1].address); - - const providers = await registry.getAddressesProvidersList(); - - expect(providers.length).to.be.equal(2, 'Invalid length of the addresses providers list'); - expect(providers[0].toString()).to.be.equal( - addressesProvider.address, - ' Invalid addresses provider added to the list' - ); - expect(providers[1].toString()).to.be.equal(ZERO_ADDRESS, ' Invalid addresses'); - }); - - it('Tries to remove a unregistered addressesProvider', async () => { - const { LPAPR_PROVIDER_NOT_REGISTERED } = ProtocolErrors; - - const { users, registry } = testEnv; - - await expect(registry.unregisterAddressesProvider(users[2].address)).to.be.revertedWith( - LPAPR_PROVIDER_NOT_REGISTERED - ); - }); - - it('Tries to remove a unregistered addressesProvider', async () => { - const { LPAPR_PROVIDER_NOT_REGISTERED } = ProtocolErrors; - - const { users, registry } = testEnv; - - await expect(registry.unregisterAddressesProvider(users[2].address)).to.be.revertedWith( - LPAPR_PROVIDER_NOT_REGISTERED - ); - }); - - it('Tries to add an already added addressesProvider with a different id. Should overwrite the previous id', async () => { - const { users, registry, addressesProvider } = testEnv; - - await registry.registerAddressesProvider(addressesProvider.address, '2'); - - const providers = await registry.getAddressesProvidersList(); - - const id = await registry.getAddressesProviderIdByAddress(addressesProvider.address); - - expect(providers.length).to.be.equal(2, 'Invalid length of the addresses providers list'); - - expect(providers[0].toString()).to.be.equal( - addressesProvider.address, - ' Invalid addresses provider added to the list' - ); - expect(providers[1].toString()).to.be.equal(ZERO_ADDRESS, ' Invalid addresses'); - }); -}); diff --git a/test/atoken-modifiers.spec.ts b/test/atoken-modifiers.spec.ts deleted file mode 100644 index d379210c..00000000 --- a/test/atoken-modifiers.spec.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { expect } from 'chai'; -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { ProtocolErrors } from '../helpers/types'; - -makeSuite('AToken: Modifiers', (testEnv: TestEnv) => { - const { CT_CALLER_MUST_BE_LENDING_POOL } = ProtocolErrors; - - it('Tries to invoke mint not being the LendingPool', async () => { - const { deployer, aDai } = testEnv; - await expect(aDai.mint(deployer.address, '1', '1')).to.be.revertedWith( - CT_CALLER_MUST_BE_LENDING_POOL - ); - }); - - it('Tries to invoke burn not being the LendingPool', async () => { - const { deployer, aDai } = testEnv; - await expect(aDai.burn(deployer.address, deployer.address, '1', '1')).to.be.revertedWith( - CT_CALLER_MUST_BE_LENDING_POOL - ); - }); - - it('Tries to invoke transferOnLiquidation not being the LendingPool', async () => { - const { deployer, users, aDai } = testEnv; - await expect( - aDai.transferOnLiquidation(deployer.address, users[0].address, '1') - ).to.be.revertedWith(CT_CALLER_MUST_BE_LENDING_POOL); - }); - - it('Tries to invoke transferUnderlyingTo not being the LendingPool', async () => { - const { deployer, aDai } = testEnv; - await expect(aDai.transferUnderlyingTo(deployer.address, '1')).to.be.revertedWith( - CT_CALLER_MUST_BE_LENDING_POOL - ); - }); -}); diff --git a/test/atoken-permit.spec.ts b/test/atoken-permit.spec.ts deleted file mode 100644 index bb880fee..00000000 --- a/test/atoken-permit.spec.ts +++ /dev/null @@ -1,312 +0,0 @@ -import { MAX_UINT_AMOUNT, ZERO_ADDRESS } from '../helpers/constants'; -import { BUIDLEREVM_CHAINID } from '../helpers/buidler-constants'; -import { buildPermitParams, getSignatureFromTypedData } from '../helpers/contracts-helpers'; -import { expect } from 'chai'; -import { ethers } from 'ethers'; -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { DRE } from '../helpers/misc-utils'; -import { waitForTx } from '../helpers/misc-utils'; -import { _TypedDataEncoder } from 'ethers/lib/utils'; - -const { parseEther } = ethers.utils; - -makeSuite('AToken: Permit', (testEnv: TestEnv) => { - it('Checks the domain separator', async () => { - const { aDai } = testEnv; - const separator = await aDai.DOMAIN_SEPARATOR(); - - const domain = { - name: await aDai.name(), - version: '1', - chainId: DRE.network.config.chainId, - verifyingContract: aDai.address, - }; - const domainSeparator = _TypedDataEncoder.hashDomain(domain); - - expect(separator).to.be.equal(domainSeparator, 'Invalid domain separator'); - }); - - it('Get aDAI for tests', async () => { - const { dai, pool, deployer } = testEnv; - - await dai.mint(parseEther('20000')); - await dai.approve(pool.address, parseEther('20000')); - - await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); - }); - - it('Reverts submitting a permit with 0 expiration', async () => { - const { aDai, deployer, users } = testEnv; - const owner = deployer; - const spender = users[1]; - - const tokenName = await aDai.name(); - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const expiration = 0; - const nonce = (await aDai._nonces(owner.address)).toNumber(); - const permitAmount = ethers.utils.parseEther('2').toString(); - const msgParams = buildPermitParams( - chainId, - aDai.address, - '1', - tokenName, - owner.address, - spender.address, - nonce, - permitAmount, - expiration.toFixed() - ); - - const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( - '0', - 'INVALID_ALLOWANCE_BEFORE_PERMIT' - ); - - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); - - await expect( - aDai - .connect(spender.signer) - .permit(owner.address, spender.address, permitAmount, expiration, v, r, s) - ).to.be.revertedWith('INVALID_EXPIRATION'); - - expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( - '0', - 'INVALID_ALLOWANCE_AFTER_PERMIT' - ); - }); - - it('Submits a permit with maximum expiration length', async () => { - const { aDai, deployer, users } = testEnv; - const owner = deployer; - const spender = users[1]; - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const deadline = MAX_UINT_AMOUNT; - const nonce = (await aDai._nonces(owner.address)).toNumber(); - const permitAmount = parseEther('2').toString(); - const msgParams = buildPermitParams( - chainId, - aDai.address, - '1', - await aDai.name(), - owner.address, - spender.address, - nonce, - deadline, - permitAmount - ); - - const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( - '0', - 'INVALID_ALLOWANCE_BEFORE_PERMIT' - ); - - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); - - await waitForTx( - await aDai - .connect(spender.signer) - .permit(owner.address, spender.address, permitAmount, deadline, v, r, s) - ); - - expect((await aDai._nonces(owner.address)).toNumber()).to.be.equal(1); - }); - - it('Cancels the previous permit', async () => { - const { aDai, deployer, users } = testEnv; - const owner = deployer; - const spender = users[1]; - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const deadline = MAX_UINT_AMOUNT; - const nonce = (await aDai._nonces(owner.address)).toNumber(); - const permitAmount = '0'; - const msgParams = buildPermitParams( - chainId, - aDai.address, - '1', - await aDai.name(), - owner.address, - spender.address, - nonce, - deadline, - permitAmount - ); - - const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); - - expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( - ethers.utils.parseEther('2'), - 'INVALID_ALLOWANCE_BEFORE_PERMIT' - ); - - await waitForTx( - await aDai - .connect(spender.signer) - .permit(owner.address, spender.address, permitAmount, deadline, v, r, s) - ); - expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal( - permitAmount, - 'INVALID_ALLOWANCE_AFTER_PERMIT' - ); - - expect((await aDai._nonces(owner.address)).toNumber()).to.be.equal(2); - }); - - it('Tries to submit a permit with invalid nonce', async () => { - const { aDai, deployer, users } = testEnv; - const owner = deployer; - const spender = users[1]; - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const deadline = MAX_UINT_AMOUNT; - const nonce = 1000; - const permitAmount = '0'; - const msgParams = buildPermitParams( - chainId, - aDai.address, - '1', - await aDai.name(), - owner.address, - spender.address, - nonce, - deadline, - permitAmount - ); - - const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); - - await expect( - aDai - .connect(spender.signer) - .permit(owner.address, spender.address, permitAmount, deadline, v, r, s) - ).to.be.revertedWith('INVALID_SIGNATURE'); - }); - - it('Tries to submit a permit with invalid expiration (previous to the current block)', async () => { - const { aDai, deployer, users } = testEnv; - const owner = deployer; - const spender = users[1]; - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const expiration = '1'; - const nonce = (await aDai._nonces(owner.address)).toNumber(); - const permitAmount = '0'; - const msgParams = buildPermitParams( - chainId, - aDai.address, - '1', - await aDai.name(), - owner.address, - spender.address, - nonce, - expiration, - permitAmount - ); - - const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); - - await expect( - aDai - .connect(spender.signer) - .permit(owner.address, spender.address, expiration, permitAmount, v, r, s) - ).to.be.revertedWith('INVALID_EXPIRATION'); - }); - - it('Tries to submit a permit with invalid signature', async () => { - const { aDai, deployer, users } = testEnv; - const owner = deployer; - const spender = users[1]; - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const deadline = MAX_UINT_AMOUNT; - const nonce = (await aDai._nonces(owner.address)).toNumber(); - const permitAmount = '0'; - const msgParams = buildPermitParams( - chainId, - aDai.address, - '1', - await aDai.name(), - owner.address, - spender.address, - nonce, - deadline, - permitAmount - ); - - const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); - - await expect( - aDai - .connect(spender.signer) - .permit(owner.address, ZERO_ADDRESS, permitAmount, deadline, v, r, s) - ).to.be.revertedWith('INVALID_SIGNATURE'); - }); - - it('Tries to submit a permit with invalid owner', async () => { - const { aDai, deployer, users } = testEnv; - const owner = deployer; - const spender = users[1]; - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const expiration = MAX_UINT_AMOUNT; - const nonce = (await aDai._nonces(owner.address)).toNumber(); - const permitAmount = '0'; - const msgParams = buildPermitParams( - chainId, - aDai.address, - '1', - await aDai.name(), - owner.address, - spender.address, - nonce, - expiration, - permitAmount - ); - - const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); - - await expect( - aDai - .connect(spender.signer) - .permit(ZERO_ADDRESS, spender.address, expiration, permitAmount, v, r, s) - ).to.be.revertedWith('INVALID_OWNER'); - }); -}); diff --git a/test/atoken-transfer.spec.ts b/test/atoken-transfer.spec.ts deleted file mode 100644 index 7414eea9..00000000 --- a/test/atoken-transfer.spec.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, ZERO_ADDRESS } from '../helpers/constants'; -import { convertToCurrencyDecimals } from '../helpers/contracts-helpers'; -import { expect } from 'chai'; -import { ethers } from 'ethers'; -import { RateMode, ProtocolErrors } from '../helpers/types'; -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { CommonsConfig } from '../markets/aave/commons'; - -const AAVE_REFERRAL = CommonsConfig.ProtocolGlobalParams.AaveReferral; - -makeSuite('AToken: Transfer', (testEnv: TestEnv) => { - const { - INVALID_FROM_BALANCE_AFTER_TRANSFER, - INVALID_TO_BALANCE_AFTER_TRANSFER, - VL_TRANSFER_NOT_ALLOWED, - } = ProtocolErrors; - - it('User 0 deposits 1000 DAI, transfers to user 1', async () => { - const { users, pool, dai, aDai } = testEnv; - - await dai.connect(users[0].signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); - - await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - //user 1 deposits 1000 DAI - const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await pool - .connect(users[0].signer) - .deposit(dai.address, amountDAItoDeposit, users[0].address, '0'); - - 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); - - expect(fromBalance.toString()).to.be.equal('0', INVALID_FROM_BALANCE_AFTER_TRANSFER); - expect(toBalance.toString()).to.be.equal( - amountDAItoDeposit.toString(), - INVALID_TO_BALANCE_AFTER_TRANSFER - ); - }); - - 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')); - - await weth.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - await pool - .connect(users[0].signer) - .deposit(weth.address, ethers.utils.parseEther('1.0'), userAddress, '0'); - await pool - .connect(users[1].signer) - .borrow( - weth.address, - ethers.utils.parseEther('0.1'), - RateMode.Stable, - AAVE_REFERRAL, - 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), - VL_TRANSFER_NOT_ALLOWED - ).to.be.revertedWith(VL_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()); - }); -}); diff --git a/test/configurator.spec.ts b/test/configurator.spec.ts deleted file mode 100644 index 1d888db0..00000000 --- a/test/configurator.spec.ts +++ /dev/null @@ -1,386 +0,0 @@ -import { TestEnv, makeSuite } from './helpers/make-suite'; -import { APPROVAL_AMOUNT_LENDING_POOL, RAY } from '../helpers/constants'; -import { convertToCurrencyDecimals } from '../helpers/contracts-helpers'; -import { ProtocolErrors } from '../helpers/types'; -import { strategyWETH } from '../markets/aave/reservesConfigs'; - -const { expect } = require('chai'); - -makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { - const { - CALLER_NOT_POOL_ADMIN, - LPC_RESERVE_LIQUIDITY_NOT_0, - RC_INVALID_LTV, - RC_INVALID_LIQ_THRESHOLD, - RC_INVALID_LIQ_BONUS, - RC_INVALID_DECIMALS, - RC_INVALID_RESERVE_FACTOR, - } = ProtocolErrors; - - 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(RC_INVALID_RESERVE_FACTOR); - }); - - it('Deactivates the ETH reserve', async () => { - const { configurator, weth, helpersContract } = testEnv; - await configurator.deactivateReserve(weth.address); - const { isActive } = await helpersContract.getReserveConfigurationData(weth.address); - expect(isActive).to.be.equal(false); - }); - - it('Rectivates the ETH reserve', async () => { - const { configurator, weth, helpersContract } = testEnv; - await configurator.activateReserve(weth.address); - - const { isActive } = await helpersContract.getReserveConfigurationData(weth.address); - expect(isActive).to.be.equal(true); - }); - - it('Check the onlyAaveAdmin on deactivateReserve ', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator.connect(users[2].signer).deactivateReserve(weth.address), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Check the onlyAaveAdmin on activateReserve ', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator.connect(users[2].signer).activateReserve(weth.address), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Freezes the ETH reserve', async () => { - const { configurator, weth, helpersContract } = testEnv; - - await configurator.freezeReserve(weth.address); - const { - decimals, - ltv, - liquidationBonus, - liquidationThreshold, - reserveFactor, - stableBorrowRateEnabled, - borrowingEnabled, - isActive, - isFrozen, - } = await helpersContract.getReserveConfigurationData(weth.address); - - expect(borrowingEnabled).to.be.equal(true); - expect(isActive).to.be.equal(true); - expect(isFrozen).to.be.equal(true); - expect(decimals).to.be.equal(strategyWETH.reserveDecimals); - expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); - expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); - expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); - expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); - expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); - }); - - it('Unfreezes the ETH reserve', async () => { - const { configurator, helpersContract, weth } = testEnv; - await configurator.unfreezeReserve(weth.address); - - const { - decimals, - ltv, - liquidationBonus, - liquidationThreshold, - reserveFactor, - stableBorrowRateEnabled, - borrowingEnabled, - isActive, - isFrozen, - } = await helpersContract.getReserveConfigurationData(weth.address); - - expect(borrowingEnabled).to.be.equal(true); - expect(isActive).to.be.equal(true); - expect(isFrozen).to.be.equal(false); - expect(decimals).to.be.equal(strategyWETH.reserveDecimals); - expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); - expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); - expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); - expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); - expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); - }); - - it('Check the onlyAaveAdmin on freezeReserve ', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator.connect(users[2].signer).freezeReserve(weth.address), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Check the onlyAaveAdmin on unfreezeReserve ', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator.connect(users[2].signer).unfreezeReserve(weth.address), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Deactivates the ETH reserve for borrowing', async () => { - const { configurator, helpersContract, weth } = testEnv; - await configurator.disableBorrowingOnReserve(weth.address); - const { - decimals, - ltv, - liquidationBonus, - liquidationThreshold, - reserveFactor, - stableBorrowRateEnabled, - borrowingEnabled, - isActive, - isFrozen, - } = await helpersContract.getReserveConfigurationData(weth.address); - - expect(borrowingEnabled).to.be.equal(false); - expect(isActive).to.be.equal(true); - expect(isFrozen).to.be.equal(false); - expect(decimals).to.be.equal(strategyWETH.reserveDecimals); - expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); - expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); - expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); - expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); - expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); - }); - - it('Activates the ETH reserve for borrowing', async () => { - const { configurator, weth, helpersContract } = testEnv; - await configurator.enableBorrowingOnReserve(weth.address, true); - const { variableBorrowIndex } = await helpersContract.getReserveData(weth.address); - - const { - decimals, - ltv, - liquidationBonus, - liquidationThreshold, - reserveFactor, - stableBorrowRateEnabled, - borrowingEnabled, - isActive, - isFrozen, - } = await helpersContract.getReserveConfigurationData(weth.address); - - expect(borrowingEnabled).to.be.equal(true); - expect(isActive).to.be.equal(true); - expect(isFrozen).to.be.equal(false); - expect(decimals).to.be.equal(strategyWETH.reserveDecimals); - expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); - expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); - expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); - expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); - expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); - - expect(variableBorrowIndex.toString()).to.be.equal(RAY); - }); - - it('Check the onlyAaveAdmin on disableBorrowingOnReserve ', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator.connect(users[2].signer).disableBorrowingOnReserve(weth.address), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, true), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Deactivates the ETH reserve as collateral', async () => { - const { configurator, helpersContract, weth } = testEnv; - await configurator.configureReserveAsCollateral(weth.address, 0, 0, 0); - - const { - decimals, - ltv, - liquidationBonus, - liquidationThreshold, - reserveFactor, - stableBorrowRateEnabled, - borrowingEnabled, - isActive, - isFrozen, - } = await helpersContract.getReserveConfigurationData(weth.address); - - expect(borrowingEnabled).to.be.equal(true); - expect(isActive).to.be.equal(true); - expect(isFrozen).to.be.equal(false); - expect(decimals).to.be.equal(18); - expect(ltv).to.be.equal(0); - expect(liquidationThreshold).to.be.equal(0); - expect(liquidationBonus).to.be.equal(0); - expect(stableBorrowRateEnabled).to.be.equal(true); - expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); - }); - - it('Activates the ETH reserve as collateral', async () => { - const { configurator, helpersContract, weth } = testEnv; - await configurator.configureReserveAsCollateral(weth.address, '8000', '8250', '10500'); - - const { - decimals, - ltv, - liquidationBonus, - liquidationThreshold, - reserveFactor, - stableBorrowRateEnabled, - borrowingEnabled, - isActive, - isFrozen, - } = await helpersContract.getReserveConfigurationData(weth.address); - - expect(borrowingEnabled).to.be.equal(true); - expect(isActive).to.be.equal(true); - expect(isFrozen).to.be.equal(false); - expect(decimals).to.be.equal(strategyWETH.reserveDecimals); - expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); - expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); - expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); - expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); - expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); - }); - - it('Check the onlyAaveAdmin on configureReserveAsCollateral ', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator - .connect(users[2].signer) - .configureReserveAsCollateral(weth.address, '7500', '8000', '10500'), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Disable stable borrow rate on the ETH reserve', async () => { - const { configurator, helpersContract, weth } = testEnv; - await configurator.disableReserveStableRate(weth.address); - const { - decimals, - ltv, - liquidationBonus, - liquidationThreshold, - reserveFactor, - stableBorrowRateEnabled, - borrowingEnabled, - isActive, - isFrozen, - } = await helpersContract.getReserveConfigurationData(weth.address); - - expect(borrowingEnabled).to.be.equal(true); - expect(isActive).to.be.equal(true); - expect(isFrozen).to.be.equal(false); - expect(decimals).to.be.equal(strategyWETH.reserveDecimals); - expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); - expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); - expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); - expect(stableBorrowRateEnabled).to.be.equal(false); - expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); - }); - - it('Enables stable borrow rate on the ETH reserve', async () => { - const { configurator, helpersContract, weth } = testEnv; - await configurator.enableReserveStableRate(weth.address); - const { - decimals, - ltv, - liquidationBonus, - liquidationThreshold, - reserveFactor, - stableBorrowRateEnabled, - borrowingEnabled, - isActive, - isFrozen, - } = await helpersContract.getReserveConfigurationData(weth.address); - - expect(borrowingEnabled).to.be.equal(true); - expect(isActive).to.be.equal(true); - expect(isFrozen).to.be.equal(false); - expect(decimals).to.be.equal(strategyWETH.reserveDecimals); - expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); - expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); - expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); - expect(stableBorrowRateEnabled).to.be.equal(true); - expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); - }); - - it('Check the onlyAaveAdmin on disableReserveStableRate', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator.connect(users[2].signer).disableReserveStableRate(weth.address), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Check the onlyAaveAdmin on enableReserveStableRate', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator.connect(users[2].signer).enableReserveStableRate(weth.address), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Changes the reserve factor of WETH', async () => { - const { configurator, helpersContract, weth } = testEnv; - await configurator.setReserveFactor(weth.address, '1000'); - const { - decimals, - ltv, - liquidationBonus, - liquidationThreshold, - reserveFactor, - stableBorrowRateEnabled, - borrowingEnabled, - isActive, - isFrozen, - } = await helpersContract.getReserveConfigurationData(weth.address); - - expect(borrowingEnabled).to.be.equal(true); - expect(isActive).to.be.equal(true); - expect(isFrozen).to.be.equal(false); - expect(decimals).to.be.equal(strategyWETH.reserveDecimals); - expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); - expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); - expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); - expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); - expect(reserveFactor).to.be.equal(1000); - }); - - it('Check the onlyLendingPoolManager on setReserveFactor', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator.connect(users[2].signer).setReserveFactor(weth.address, '2000'), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Reverts when trying to disable the DAI reserve with liquidity on it', async () => { - const { dai, pool, configurator } = testEnv; - const userAddress = await pool.signer.getAddress(); - await dai.mint(await convertToCurrencyDecimals(dai.address, '1000')); - - //approve protocol to access depositor wallet - await dai.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - //user 1 deposits 1000 DAI - await pool.deposit(dai.address, amountDAItoDeposit, userAddress, '0'); - - await expect( - configurator.deactivateReserve(dai.address), - LPC_RESERVE_LIQUIDITY_NOT_0 - ).to.be.revertedWith(LPC_RESERVE_LIQUIDITY_NOT_0); - }); -}); diff --git a/test/delegation-aware-atoken.spec.ts b/test/delegation-aware-atoken.spec.ts deleted file mode 100644 index 7b04913e..00000000 --- a/test/delegation-aware-atoken.spec.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { MAX_UINT_AMOUNT, ZERO_ADDRESS } from '../helpers/constants'; -import { BUIDLEREVM_CHAINID } from '../helpers/buidler-constants'; -import { buildPermitParams, getSignatureFromTypedData } from '../helpers/contracts-helpers'; -import { expect } from 'chai'; -import { ethers } from 'ethers'; -import { eEthereumNetwork, ProtocolErrors } from '../helpers/types'; -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { DRE } from '../helpers/misc-utils'; -import { - ConfigNames, - getATokenDomainSeparatorPerNetwork, - getTreasuryAddress, - loadPoolConfig, -} from '../helpers/configuration'; -import { waitForTx } from '../helpers/misc-utils'; -import { - deployDelegationAwareAToken, - deployMintableDelegationERC20, -} from '../helpers/contracts-deployments'; -import { DelegationAwareATokenFactory } from '../types'; -import { DelegationAwareAToken } from '../types/DelegationAwareAToken'; -import { MintableDelegationERC20 } from '../types/MintableDelegationERC20'; -import AaveConfig from '../markets/aave'; - -const { parseEther } = ethers.utils; - -makeSuite('AToken: underlying delegation', (testEnv: TestEnv) => { - const poolConfig = loadPoolConfig(ConfigNames.Commons); - let delegationAToken = {}; - let delegationERC20 = {}; - - it('Deploys a new MintableDelegationERC20 and a DelegationAwareAToken', async () => { - const { pool } = testEnv; - - delegationERC20 = await deployMintableDelegationERC20(['DEL', 'DEL', '18']); - - delegationAToken = await deployDelegationAwareAToken( - [pool.address, delegationERC20.address, await getTreasuryAddress(AaveConfig), ZERO_ADDRESS, 'aDEL', 'aDEL'], - false - ); - - //await delegationAToken.initialize(pool.address, ZERO_ADDRESS, delegationERC20.address, ZERO_ADDRESS, '18', 'aDEL', 'aDEL'); - - console.log((await delegationAToken.decimals()).toString()); - }); - - it('Tries to delegate with the caller not being the Aave admin', async () => { - const { users } = testEnv; - - await expect( - delegationAToken.connect(users[1].signer).delegateUnderlyingTo(users[2].address) - ).to.be.revertedWith(ProtocolErrors.CALLER_NOT_POOL_ADMIN); - }); - - it('Tries to delegate to user 2', async () => { - const { users } = testEnv; - - await delegationAToken.delegateUnderlyingTo(users[2].address); - - const delegateeAddress = await delegationERC20.delegatee(); - - expect(delegateeAddress).to.be.equal(users[2].address); - }); -}); diff --git a/test/flashloan.spec.ts b/test/flashloan.spec.ts deleted file mode 100644 index c6e5dcff..00000000 --- a/test/flashloan.spec.ts +++ /dev/null @@ -1,497 +0,0 @@ -import BigNumber from 'bignumber.js'; - -import { TestEnv, makeSuite } from './helpers/make-suite'; -import { APPROVAL_AMOUNT_LENDING_POOL, oneRay } from '../helpers/constants'; -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, - getStableDebtToken, - getVariableDebtToken, -} from '../helpers/contracts-getters'; - -const { expect } = require('chai'); - -makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { - let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver; - const { - VL_COLLATERAL_BALANCE_IS_0, - TRANSFER_AMOUNT_EXCEEDS_BALANCE, - LP_INVALID_FLASHLOAN_MODE, - SAFEERC20_LOWLEVEL_CALL, - LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN, - LP_BORROW_ALLOWANCE_NOT_ENOUGH, - } = ProtocolErrors; - - before(async () => { - _mockFlashLoanReceiver = await getMockFlashLoanReceiver(); - }); - - it('Deposits WETH into the reserve', async () => { - const { pool, weth } = testEnv; - const userAddress = await pool.signer.getAddress(); - const amountToDeposit = ethers.utils.parseEther('1'); - - await weth.mint(amountToDeposit); - - await weth.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - await pool.deposit(weth.address, amountToDeposit, userAddress, '0'); - }); - - it('Takes WETH flashloan with mode = 0, returns the funds correctly', async () => { - const { pool, helpersContract, weth } = testEnv; - - await pool.flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [ethers.utils.parseEther('0.8')], - [0], - _mockFlashLoanReceiver.address, - '0x10', - '0' - ); - - ethers.utils.parseUnits('10000'); - - const reserveData = await helpersContract.getReserveData(weth.address); - - const currentLiquidityRate = reserveData.liquidityRate; - const currentLiquidityIndex = reserveData.liquidityIndex; - - const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) - .plus(reserveData.totalStableDebt.toString()) - .plus(reserveData.totalVariableDebt.toString()); - - expect(totalLiquidity.toString()).to.be.equal('1000720000000000000'); - expect(currentLiquidityRate.toString()).to.be.equal('0'); - expect(currentLiquidityIndex.toString()).to.be.equal('1000720000000000000000000000'); - }); - - it('Takes an ETH flashloan with mode = 0 as big as the available liquidity', async () => { - const { pool, helpersContract, weth } = testEnv; - - const reserveDataBefore = await helpersContract.getReserveData(weth.address); - const txResult = await pool.flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - ['1000720000000000000'], - [0], - _mockFlashLoanReceiver.address, - '0x10', - '0' - ); - - const reserveData = await helpersContract.getReserveData(weth.address); - - const currentLiqudityRate = reserveData.liquidityRate; - const currentLiquidityIndex = reserveData.liquidityIndex; - - const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) - .plus(reserveData.totalStableDebt.toString()) - .plus(reserveData.totalVariableDebt.toString()); - - expect(totalLiquidity.toString()).to.be.equal('1001620648000000000'); - expect(currentLiqudityRate.toString()).to.be.equal('0'); - expect(currentLiquidityIndex.toString()).to.be.equal('1001620648000000000000000000'); - }); - - it('Takes WETH flashloan, does not return the funds with mode = 0. (revert expected)', async () => { - const { pool, weth, users } = testEnv; - const caller = users[1]; - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - await expect( - pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [ethers.utils.parseEther('0.8')], - [0], - caller.address, - '0x10', - '0' - ) - ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); - }); - - it('Takes WETH flashloan, simulating a receiver as EOA (revert expected)', async () => { - const { pool, weth, users } = testEnv; - const caller = users[1]; - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - await _mockFlashLoanReceiver.setSimulateEOA(true); - - await expect( - pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [ethers.utils.parseEther('0.8')], - [0], - caller.address, - '0x10', - '0' - ) - ).to.be.revertedWith(LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN); - }); - - it('Takes a WETH flashloan with an invalid mode. (revert expected)', async () => { - const { pool, weth, users } = testEnv; - const caller = users[1]; - await _mockFlashLoanReceiver.setSimulateEOA(false); - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - await expect( - pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [ethers.utils.parseEther('0.8')], - [4], - caller.address, - '0x10', - '0' - ) - ).to.be.reverted; - }); - - it('Caller deposits 1000 DAI as collateral, Takes WETH flashloan with mode = 2, does not return the funds. A variable loan for caller is created', async () => { - const { dai, pool, weth, users, helpersContract } = testEnv; - - const caller = users[1]; - - await dai.connect(caller.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); - - await dai.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const amountToDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await pool.connect(caller.signer).deposit(dai.address, amountToDeposit, caller.address, '0'); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - await pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [ethers.utils.parseEther('0.8')], - [2], - caller.address, - '0x10', - '0' - ); - const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - weth.address - ); - - const wethDebtToken = await getVariableDebtToken(variableDebtTokenAddress); - - const callerDebt = await wethDebtToken.balanceOf(caller.address); - - expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt'); - }); - - it('tries to take a flashloan that is bigger than the available liquidity (revert expected)', async () => { - const { pool, weth, users } = testEnv; - const caller = users[1]; - - await expect( - pool.connect(caller.signer).flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - ['1004415000000000000'], //slightly higher than the available liquidity - [2], - caller.address, - '0x10', - '0' - ), - TRANSFER_AMOUNT_EXCEEDS_BALANCE - ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); - }); - - it('tries to take a flashloan using a non contract address as receiver (revert expected)', async () => { - const { pool, deployer, weth, users } = testEnv; - const caller = users[1]; - - await expect( - pool.flashLoan( - deployer.address, - [weth.address], - ['1000000000000000000'], - [2], - caller.address, - '0x10', - '0' - ) - ).to.be.reverted; - }); - - it('Deposits USDC into the reserve', async () => { - const { usdc, pool } = testEnv; - const userAddress = await pool.signer.getAddress(); - - await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000')); - - await usdc.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const amountToDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); - - await pool.deposit(usdc.address, amountToDeposit, userAddress, '0'); - }); - - it('Takes out a 500 USDC flashloan, returns the funds correctly', async () => { - const { usdc, pool, helpersContract, deployer: depositor } = testEnv; - - await _mockFlashLoanReceiver.setFailExecutionTransfer(false); - - const reserveDataBefore = await helpersContract.getReserveData(usdc.address); - - const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); - - await pool.flashLoan( - _mockFlashLoanReceiver.address, - [usdc.address], - [flashloanAmount], - [0], - _mockFlashLoanReceiver.address, - '0x10', - '0' - ); - - const reserveDataAfter = helpersContract.getReserveData(usdc.address); - - const reserveData = await helpersContract.getReserveData(usdc.address); - const userData = await helpersContract.getUserReserveData(usdc.address, depositor.address); - - const totalLiquidity = reserveData.availableLiquidity - .add(reserveData.totalStableDebt) - .add(reserveData.totalVariableDebt) - .toString(); - const currentLiqudityRate = reserveData.liquidityRate.toString(); - const currentLiquidityIndex = reserveData.liquidityIndex.toString(); - const currentUserBalance = userData.currentATokenBalance.toString(); - - const expectedLiquidity = await convertToCurrencyDecimals(usdc.address, '1000.450'); - - expect(totalLiquidity).to.be.equal(expectedLiquidity, 'Invalid total liquidity'); - expect(currentLiqudityRate).to.be.equal('0', 'Invalid liquidity rate'); - expect(currentLiquidityIndex).to.be.equal( - new BigNumber('1.00045').multipliedBy(oneRay).toFixed(), - 'Invalid liquidity index' - ); - expect(currentUserBalance.toString()).to.be.equal(expectedLiquidity, 'Invalid user balance'); - }); - - it('Takes out a 500 USDC flashloan with mode = 0, does not return the funds. (revert expected)', async () => { - const { usdc, pool, users } = testEnv; - const caller = users[2]; - - const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - await expect( - pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [usdc.address], - [flashloanAmount], - [2], - caller.address, - '0x10', - '0' - ) - ).to.be.revertedWith(VL_COLLATERAL_BALANCE_IS_0); - }); - - it('Caller deposits 5 WETH as collateral, Takes a USDC flashloan with mode = 2, does not return the funds. A loan for caller is created', async () => { - const { usdc, pool, weth, users, helpersContract } = testEnv; - - const caller = users[2]; - - await weth.connect(caller.signer).mint(await convertToCurrencyDecimals(weth.address, '5')); - - await weth.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const amountToDeposit = await convertToCurrencyDecimals(weth.address, '5'); - - await pool.connect(caller.signer).deposit(weth.address, amountToDeposit, caller.address, '0'); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); - - await pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [usdc.address], - [flashloanAmount], - [2], - caller.address, - '0x10', - '0' - ); - const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - usdc.address - ); - - const usdcDebtToken = await getVariableDebtToken(variableDebtTokenAddress); - - const callerDebt = await usdcDebtToken.balanceOf(caller.address); - - expect(callerDebt.toString()).to.be.equal('500000000', 'Invalid user debt'); - }); - - it('Caller deposits 1000 DAI as collateral, Takes a WETH flashloan with mode = 0, does not approve the transfer of the funds', async () => { - const { dai, pool, weth, users } = testEnv; - const caller = users[3]; - - await dai.connect(caller.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); - - await dai.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const amountToDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await pool.connect(caller.signer).deposit(dai.address, amountToDeposit, caller.address, '0'); - - const flashAmount = ethers.utils.parseEther('0.8'); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(false); - await _mockFlashLoanReceiver.setAmountToApprove(flashAmount.div(2)); - - await expect( - pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [flashAmount], - [0], - caller.address, - '0x10', - '0' - ) - ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); - }); - - it('Caller takes a WETH flashloan with mode = 1', async () => { - const { dai, pool, weth, users, helpersContract } = testEnv; - - const caller = users[3]; - - const flashAmount = ethers.utils.parseEther('0.8'); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - await pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [flashAmount], - [1], - caller.address, - '0x10', - '0' - ); - - const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - weth.address - ); - - const wethDebtToken = await getStableDebtToken(stableDebtTokenAddress); - - const callerDebt = await wethDebtToken.balanceOf(caller.address); - - 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(LP_BORROW_ALLOWANCE_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'); - - const reserveData = await pool.getReserveData(weth.address); - - const stableDebtToken = await getVariableDebtToken(reserveData.stableDebtTokenAddress); - - // Deposited for onBehalfOf user already, delegate borrow allowance - await stableDebtToken.connect(onBehalfOf.signer).approveDelegation(caller.address, 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 getStableDebtToken(stableDebtTokenAddress); - - const onBehalfOfDebt = await wethDebtToken.balanceOf(onBehalfOf.address); - - expect(onBehalfOfDebt.toString()).to.be.equal( - '800000000000000000', - 'Invalid onBehalfOf user debt' - ); - }); -}); diff --git a/test/helpers/actions.ts b/test/helpers/actions.ts deleted file mode 100644 index 7b0081ce..00000000 --- a/test/helpers/actions.ts +++ /dev/null @@ -1,772 +0,0 @@ -import BigNumber from 'bignumber.js'; - -import { - calcExpectedReserveDataAfterBorrow, - calcExpectedReserveDataAfterDeposit, - calcExpectedReserveDataAfterRepay, - calcExpectedReserveDataAfterStableRateRebalance, - calcExpectedReserveDataAfterSwapRateMode, - calcExpectedReserveDataAfterWithdraw, - calcExpectedUserDataAfterBorrow, - calcExpectedUserDataAfterDeposit, - calcExpectedUserDataAfterRepay, - calcExpectedUserDataAfterSetUseAsCollateral, - calcExpectedUserDataAfterStableRateRebalance, - calcExpectedUserDataAfterSwapRateMode, - calcExpectedUserDataAfterWithdraw, -} from './utils/calculations'; -import { getReserveAddressFromSymbol, getReserveData, getUserData } from './utils/helpers'; - -import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; -import { - getAToken, - getMintableERC20, - getStableDebtToken, - getVariableDebtToken, -} from '../../helpers/contracts-getters'; -import { MAX_UINT_AMOUNT, ONE_YEAR } from '../../helpers/constants'; -import { SignerWithAddress, TestEnv } from './make-suite'; -import { advanceTimeAndBlock, DRE, timeLatest, waitForTx } from '../../helpers/misc-utils'; - -import chai from 'chai'; -import { ReserveData, UserReserveData } from './utils/interfaces'; -import { ContractReceipt } from 'ethers'; -import { AToken } from '../../types/AToken'; -import { RateMode, tEthereumAddress } from '../../helpers/types'; - -const { expect } = chai; - -const almostEqualOrEqual = function ( - this: any, - expected: ReserveData | UserReserveData, - actual: ReserveData | UserReserveData -) { - const keys = Object.keys(actual); - - keys.forEach((key) => { - if ( - key === 'lastUpdateTimestamp' || - key === 'marketStableRate' || - key === 'symbol' || - key === 'aTokenAddress' || - key === 'decimals' || - key === 'totalStableDebtLastUpdated' - ) { - // skipping consistency check on accessory data - return; - } - - this.assert(actual[key] != undefined, `Property ${key} is undefined in the actual data`); - expect(expected[key] != undefined, `Property ${key} is undefined in the expected data`); - - if (expected[key] == null || actual[key] == null) { - console.log('Found a undefined value for Key ', key, ' value ', expected[key], actual[key]); - } - - if (actual[key] instanceof BigNumber) { - const actualValue = (actual[key]).decimalPlaces(0, BigNumber.ROUND_DOWN); - const expectedValue = (expected[key]).decimalPlaces(0, BigNumber.ROUND_DOWN); - - this.assert( - actualValue.eq(expectedValue) || - actualValue.plus(1).eq(expectedValue) || - actualValue.eq(expectedValue.plus(1)) || - actualValue.plus(2).eq(expectedValue) || - actualValue.eq(expectedValue.plus(2)) || - actualValue.plus(3).eq(expectedValue) || - actualValue.eq(expectedValue.plus(3)), - `expected #{act} to be almost equal or equal #{exp} for property ${key}`, - `expected #{act} to be almost equal or equal #{exp} for property ${key}`, - expectedValue.toFixed(0), - actualValue.toFixed(0) - ); - } else { - this.assert( - actual[key] !== null && - expected[key] !== null && - actual[key].toString() === expected[key].toString(), - `expected #{act} to be equal #{exp} for property ${key}`, - `expected #{act} to be equal #{exp} for property ${key}`, - expected[key], - actual[key] - ); - } - }); -}; - -chai.use(function (chai: any, utils: any) { - chai.Assertion.overwriteMethod('almostEqualOrEqual', function (original: any) { - return function (this: any, expected: ReserveData | UserReserveData) { - const actual = (expected as ReserveData) - ? this._obj - : this._obj; - - almostEqualOrEqual.apply(this, [expected, actual]); - }; - }); -}); - -interface ActionsConfig { - skipIntegrityCheck: boolean; -} - -export const configuration: ActionsConfig = {}; - -export const mint = async (reserveSymbol: string, amount: string, user: SignerWithAddress) => { - const reserve = await getReserveAddressFromSymbol(reserveSymbol); - - const token = await getMintableERC20(reserve); - - await waitForTx( - await token.connect(user.signer).mint(await convertToCurrencyDecimals(reserve, amount)) - ); -}; - -export const approve = async (reserveSymbol: string, user: SignerWithAddress, testEnv: TestEnv) => { - const { pool } = testEnv; - const reserve = await getReserveAddressFromSymbol(reserveSymbol); - - const token = await getMintableERC20(reserve); - - await waitForTx( - await token.connect(user.signer).approve(pool.address, '100000000000000000000000000000') - ); -}; - -export const deposit = async ( - reserveSymbol: string, - amount: string, - sender: SignerWithAddress, - onBehalfOf: tEthereumAddress, - sendValue: string, - expectedResult: string, - testEnv: TestEnv, - revertMessage?: string -) => { - const { pool } = testEnv; - - const reserve = await getReserveAddressFromSymbol(reserveSymbol); - - const amountToDeposit = await convertToCurrencyDecimals(reserve, amount); - - const txOptions: any = {}; - - const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( - reserve, - onBehalfOf, - testEnv, - sender.address - ); - - if (sendValue) { - txOptions.value = await convertToCurrencyDecimals(reserve, sendValue); - } - - //console.log("Depositing %s %s, expecting %s", amountToDeposit.toString(), reserveSymbol, expectedResult); - - if (expectedResult === 'success') { - const txResult = await waitForTx( - await pool - .connect(sender.signer) - .deposit(reserve, amountToDeposit, onBehalfOf, '0', txOptions) - ); - - const { - reserveData: reserveDataAfter, - userData: userDataAfter, - timestamp, - } = await getContractsData(reserve, onBehalfOf, testEnv, sender.address); - - const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); - - const expectedReserveData = calcExpectedReserveDataAfterDeposit( - amountToDeposit.toString(), - reserveDataBefore, - txTimestamp - ); - - const expectedUserReserveData = calcExpectedUserDataAfterDeposit( - amountToDeposit.toString(), - reserveDataBefore, - expectedReserveData, - userDataBefore, - txTimestamp, - timestamp, - txCost - ); - - expectEqual(reserveDataAfter, expectedReserveData); - expectEqual(userDataAfter, expectedUserReserveData); - - // truffleAssert.eventEmitted(txResult, "Deposit", (ev: any) => { - // const {_reserve, _user, _amount} = ev; - // return ( - // _reserve === reserve && - // _user === user && - // new BigNumber(_amount).isEqualTo(new BigNumber(amountToDeposit)) - // ); - // }); - } else if (expectedResult === 'revert') { - await expect( - pool.connect(sender.signer).deposit(reserve, amountToDeposit, onBehalfOf, '0', txOptions), - revertMessage - ).to.be.reverted; - } -}; - -export const withdraw = async ( - reserveSymbol: string, - amount: string, - user: SignerWithAddress, - expectedResult: string, - testEnv: TestEnv, - revertMessage?: string -) => { - const { pool } = testEnv; - - const { - aTokenInstance, - reserve, - userData: userDataBefore, - reserveData: reserveDataBefore, - } = await getDataBeforeAction(reserveSymbol, user.address, testEnv); - - let amountToWithdraw = '0'; - - if (amount !== '-1') { - amountToWithdraw = (await convertToCurrencyDecimals(reserve, amount)).toString(); - } else { - amountToWithdraw = MAX_UINT_AMOUNT; - } - - if (expectedResult === 'success') { - const txResult = await waitForTx( - await pool.connect(user.signer).withdraw(reserve, amountToWithdraw, user.address) - ); - - const { - reserveData: reserveDataAfter, - userData: userDataAfter, - timestamp, - } = await getContractsData(reserve, user.address, testEnv); - - const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); - - const expectedReserveData = calcExpectedReserveDataAfterWithdraw( - amountToWithdraw, - reserveDataBefore, - userDataBefore, - txTimestamp - ); - - const expectedUserData = calcExpectedUserDataAfterWithdraw( - amountToWithdraw, - reserveDataBefore, - expectedReserveData, - userDataBefore, - txTimestamp, - timestamp, - txCost - ); - - expectEqual(reserveDataAfter, expectedReserveData); - expectEqual(userDataAfter, expectedUserData); - - // truffleAssert.eventEmitted(txResult, "Redeem", (ev: any) => { - // const {_from, _value} = ev; - // return ( - // _from === user && new BigNumber(_value).isEqualTo(actualAmountRedeemed) - // ); - // }); - } else if (expectedResult === 'revert') { - await expect( - pool.connect(user.signer).withdraw(reserve, amountToWithdraw, user.address), - revertMessage - ).to.be.reverted; - } -}; - -export const delegateBorrowAllowance = async ( - reserve: string, - amount: string, - interestRateMode: string, - user: SignerWithAddress, - receiver: tEthereumAddress, - expectedResult: string, - testEnv: TestEnv, - revertMessage?: string -) => { - const { pool } = testEnv; - - const reserveAddress: tEthereumAddress = await getReserveAddressFromSymbol(reserve); - - const amountToDelegate: string = await ( - await convertToCurrencyDecimals(reserveAddress, amount) - ).toString(); - - const reserveData = await pool.getReserveData(reserveAddress); - - const debtToken = - interestRateMode === '1' - ? await getStableDebtToken(reserveData.stableDebtTokenAddress) - : await getVariableDebtToken(reserveData.variableDebtTokenAddress); - - const delegateAllowancePromise = debtToken - .connect(user.signer) - .approveDelegation(receiver, amountToDelegate); - - if (expectedResult === 'revert' && revertMessage) { - await expect(delegateAllowancePromise, revertMessage).to.be.revertedWith(revertMessage); - return; - } else { - await waitForTx(await delegateAllowancePromise); - const allowance = await debtToken.borrowAllowance(user.address, receiver); - expect(allowance.toString()).to.be.equal( - amountToDelegate, - 'borrowAllowance is set incorrectly' - ); - } -}; - -export const borrow = async ( - reserveSymbol: string, - amount: string, - interestRateMode: string, - user: SignerWithAddress, - onBehalfOf: tEthereumAddress, - timeTravel: string, - expectedResult: string, - testEnv: TestEnv, - revertMessage?: string -) => { - const { pool } = testEnv; - - const reserve = await getReserveAddressFromSymbol(reserveSymbol); - - const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( - reserve, - onBehalfOf, - testEnv, - user.address - ); - - const amountToBorrow = await convertToCurrencyDecimals(reserve, amount); - //console.log("Borrowing %s %s with rate mode %s expecting", amountToBorrow.toString(), reserveSymbol, interestRateMode, expectedResult); - if (expectedResult === 'success') { - const txResult = await waitForTx( - await pool - .connect(user.signer) - .borrow(reserve, amountToBorrow, interestRateMode, '0', onBehalfOf) - ); - - const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); - - if (timeTravel) { - const secondsToTravel = new BigNumber(timeTravel).multipliedBy(ONE_YEAR).div(365).toNumber(); - - await advanceTimeAndBlock(secondsToTravel); - } - - const { - reserveData: reserveDataAfter, - userData: userDataAfter, - timestamp, - } = await getContractsData(reserve, onBehalfOf, testEnv, user.address); - - const expectedReserveData = calcExpectedReserveDataAfterBorrow( - amountToBorrow.toString(), - interestRateMode, - reserveDataBefore, - userDataBefore, - txTimestamp, - timestamp - ); - - const expectedUserData = calcExpectedUserDataAfterBorrow( - amountToBorrow.toString(), - interestRateMode, - reserveDataBefore, - expectedReserveData, - userDataBefore, - txTimestamp, - timestamp - ); - - expectEqual(reserveDataAfter, expectedReserveData); - expectEqual(userDataAfter, expectedUserData); - - // truffleAssert.eventEmitted(txResult, "Borrow", (ev: any) => { - // const { - // _reserve, - // _user, - // _amount, - // _borrowRateMode, - // _borrowRate, - // _originationFee, - // } = ev; - // return ( - // _reserve.toLowerCase() === reserve.toLowerCase() && - // _user.toLowerCase() === user.toLowerCase() && - // new BigNumber(_amount).eq(amountToBorrow) && - // new BigNumber(_borrowRateMode).eq(expectedUserData.borrowRateMode) && - // new BigNumber(_borrowRate).eq(expectedUserData.borrowRate) && - // new BigNumber(_originationFee).eq( - // expectedUserData.originationFee.minus(userDataBefore.originationFee) - // ) - // ); - // }); - } else if (expectedResult === 'revert') { - await expect( - pool.connect(user.signer).borrow(reserve, amountToBorrow, interestRateMode, '0', onBehalfOf), - revertMessage - ).to.be.reverted; - } -}; - -export const repay = async ( - reserveSymbol: string, - amount: string, - rateMode: string, - user: SignerWithAddress, - onBehalfOf: SignerWithAddress, - sendValue: string, - expectedResult: string, - testEnv: TestEnv, - revertMessage?: string -) => { - const { pool } = testEnv; - const reserve = await getReserveAddressFromSymbol(reserveSymbol); - - const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( - reserve, - onBehalfOf.address, - testEnv - ); - - let amountToRepay = '0'; - - if (amount !== '-1') { - amountToRepay = (await convertToCurrencyDecimals(reserve, amount)).toString(); - } else { - amountToRepay = MAX_UINT_AMOUNT; - } - amountToRepay = '0x' + new BigNumber(amountToRepay).toString(16); - - const txOptions: any = {}; - - if (sendValue) { - const valueToSend = await convertToCurrencyDecimals(reserve, sendValue); - txOptions.value = '0x' + new BigNumber(valueToSend.toString()).toString(16); - } - - if (expectedResult === 'success') { - const txResult = await waitForTx( - await pool - .connect(user.signer) - .repay(reserve, amountToRepay, rateMode, onBehalfOf.address, txOptions) - ); - - const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); - - const { - reserveData: reserveDataAfter, - userData: userDataAfter, - timestamp, - } = await getContractsData(reserve, onBehalfOf.address, testEnv); - - const expectedReserveData = calcExpectedReserveDataAfterRepay( - amountToRepay, - rateMode, - reserveDataBefore, - userDataBefore, - txTimestamp, - timestamp - ); - - const expectedUserData = calcExpectedUserDataAfterRepay( - amountToRepay, - rateMode, - reserveDataBefore, - expectedReserveData, - userDataBefore, - user.address, - onBehalfOf.address, - txTimestamp, - timestamp - ); - - expectEqual(reserveDataAfter, expectedReserveData); - expectEqual(userDataAfter, expectedUserData); - - // truffleAssert.eventEmitted(txResult, "Repay", (ev: any) => { - // const {_reserve, _user, _repayer} = ev; - - // return ( - // _reserve.toLowerCase() === reserve.toLowerCase() && - // _user.toLowerCase() === onBehalfOf.toLowerCase() && - // _repayer.toLowerCase() === user.toLowerCase() - // ); - // }); - } else if (expectedResult === 'revert') { - await expect( - pool - .connect(user.signer) - .repay(reserve, amountToRepay, rateMode, onBehalfOf.address, txOptions), - revertMessage - ).to.be.reverted; - } -}; - -export const setUseAsCollateral = async ( - reserveSymbol: string, - user: SignerWithAddress, - useAsCollateral: string, - expectedResult: string, - testEnv: TestEnv, - revertMessage?: string -) => { - const { pool } = testEnv; - - const reserve = await getReserveAddressFromSymbol(reserveSymbol); - - const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( - reserve, - user.address, - testEnv - ); - - const useAsCollateralBool = useAsCollateral.toLowerCase() === 'true'; - - if (expectedResult === 'success') { - const txResult = await waitForTx( - await pool.connect(user.signer).setUserUseReserveAsCollateral(reserve, useAsCollateralBool) - ); - - const { txCost } = await getTxCostAndTimestamp(txResult); - - const { userData: userDataAfter } = await getContractsData(reserve, user.address, testEnv); - - const expectedUserData = calcExpectedUserDataAfterSetUseAsCollateral( - useAsCollateral.toLocaleLowerCase() === 'true', - reserveDataBefore, - userDataBefore, - txCost - ); - - expectEqual(userDataAfter, expectedUserData); - // if (useAsCollateralBool) { - // truffleAssert.eventEmitted(txResult, 'ReserveUsedAsCollateralEnabled', (ev: any) => { - // const {_reserve, _user} = ev; - // return _reserve === reserve && _user === user; - // }); - // } else { - // truffleAssert.eventEmitted(txResult, 'ReserveUsedAsCollateralDisabled', (ev: any) => { - // const {_reserve, _user} = ev; - // return _reserve === reserve && _user === user; - // }); - // } - } else if (expectedResult === 'revert') { - await expect( - pool.connect(user.signer).setUserUseReserveAsCollateral(reserve, useAsCollateralBool), - revertMessage - ).to.be.reverted; - } -}; - -export const swapBorrowRateMode = async ( - reserveSymbol: string, - user: SignerWithAddress, - rateMode: string, - expectedResult: string, - testEnv: TestEnv, - revertMessage?: string -) => { - const { pool } = testEnv; - - const reserve = await getReserveAddressFromSymbol(reserveSymbol); - - const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( - reserve, - user.address, - testEnv - ); - - if (expectedResult === 'success') { - const txResult = await waitForTx( - await pool.connect(user.signer).swapBorrowRateMode(reserve, rateMode) - ); - - const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); - - const { reserveData: reserveDataAfter, userData: userDataAfter } = await getContractsData( - reserve, - user.address, - testEnv - ); - - const expectedReserveData = calcExpectedReserveDataAfterSwapRateMode( - reserveDataBefore, - userDataBefore, - rateMode, - txTimestamp - ); - - const expectedUserData = calcExpectedUserDataAfterSwapRateMode( - reserveDataBefore, - expectedReserveData, - userDataBefore, - rateMode, - txCost, - txTimestamp - ); - - expectEqual(reserveDataAfter, expectedReserveData); - expectEqual(userDataAfter, expectedUserData); - - // truffleAssert.eventEmitted(txResult, "Swap", (ev: any) => { - // const {_user, _reserve, _newRateMode, _newRate} = ev; - // return ( - // _user === user && - // _reserve == reserve && - // new BigNumber(_newRateMode).eq(expectedUserData.borrowRateMode) && - // new BigNumber(_newRate).eq(expectedUserData.borrowRate) - // ); - // }); - } else if (expectedResult === 'revert') { - await expect(pool.connect(user.signer).swapBorrowRateMode(reserve, rateMode), revertMessage).to - .be.reverted; - } -}; - -export const rebalanceStableBorrowRate = async ( - reserveSymbol: string, - user: SignerWithAddress, - target: SignerWithAddress, - expectedResult: string, - testEnv: TestEnv, - revertMessage?: string -) => { - const { pool } = testEnv; - - const reserve = await getReserveAddressFromSymbol(reserveSymbol); - - const { reserveData: reserveDataBefore, userData: userDataBefore } = await getContractsData( - reserve, - target.address, - testEnv - ); - - if (expectedResult === 'success') { - const txResult = await waitForTx( - await pool.connect(user.signer).rebalanceStableBorrowRate(reserve, target.address) - ); - - const { txCost, txTimestamp } = await getTxCostAndTimestamp(txResult); - - const { reserveData: reserveDataAfter, userData: userDataAfter } = await getContractsData( - reserve, - target.address, - testEnv - ); - - const expectedReserveData = calcExpectedReserveDataAfterStableRateRebalance( - reserveDataBefore, - userDataBefore, - txTimestamp - ); - - const expectedUserData = calcExpectedUserDataAfterStableRateRebalance( - reserveDataBefore, - expectedReserveData, - userDataBefore, - txCost, - txTimestamp - ); - - expectEqual(reserveDataAfter, expectedReserveData); - expectEqual(userDataAfter, expectedUserData); - - // truffleAssert.eventEmitted(txResult, 'RebalanceStableBorrowRate', (ev: any) => { - // const {_user, _reserve, _newStableRate} = ev; - // return ( - // _user.toLowerCase() === target.toLowerCase() && - // _reserve.toLowerCase() === reserve.toLowerCase() && - // new BigNumber(_newStableRate).eq(expectedUserData.borrowRate) - // ); - // }); - } else if (expectedResult === 'revert') { - await expect( - pool.connect(user.signer).rebalanceStableBorrowRate(reserve, target.address), - revertMessage - ).to.be.reverted; - } -}; - -const expectEqual = ( - actual: UserReserveData | ReserveData, - expected: UserReserveData | ReserveData -) => { - if (!configuration.skipIntegrityCheck) { - // @ts-ignore - expect(actual).to.be.almostEqualOrEqual(expected); - } -}; - -interface ActionData { - reserve: string; - reserveData: ReserveData; - userData: UserReserveData; - aTokenInstance: AToken; -} - -const getDataBeforeAction = async ( - reserveSymbol: string, - user: tEthereumAddress, - testEnv: TestEnv -): Promise => { - const reserve = await getReserveAddressFromSymbol(reserveSymbol); - - const { reserveData, userData } = await getContractsData(reserve, user, testEnv); - const aTokenInstance = await getAToken(reserveData.aTokenAddress); - return { - reserve, - reserveData, - userData, - aTokenInstance, - }; -}; - -export const getTxCostAndTimestamp = async (tx: ContractReceipt) => { - if (!tx.blockNumber || !tx.transactionHash || !tx.cumulativeGasUsed) { - throw new Error('No tx blocknumber'); - } - const txTimestamp = new BigNumber((await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp); - - const txInfo = await DRE.ethers.provider.getTransaction(tx.transactionHash); - const txCost = new BigNumber(tx.cumulativeGasUsed.toString()).multipliedBy( - txInfo.gasPrice.toString() - ); - - return { txCost, txTimestamp }; -}; - -export const getContractsData = async ( - reserve: string, - user: string, - testEnv: TestEnv, - sender?: string -) => { - const { pool, helpersContract } = testEnv; - - const [userData, reserveData, timestamp] = await Promise.all([ - getUserData(pool, helpersContract, reserve, user, sender || user), - getReserveData(helpersContract, reserve), - timeLatest(), - ]); - - return { - reserveData, - userData, - timestamp: new BigNumber(timestamp), - }; -}; diff --git a/test/helpers/almost-equal.ts b/test/helpers/almost-equal.ts deleted file mode 100644 index e0017056..00000000 --- a/test/helpers/almost-equal.ts +++ /dev/null @@ -1,31 +0,0 @@ -import BigNumber from 'bignumber.js'; - -function almostEqualAssertion(this: any, expected: any, actual: any, message: string): any { - this.assert( - expected.plus(new BigNumber(1)).eq(actual) || - expected.plus(new BigNumber(2)).eq(actual) || - actual.plus(new BigNumber(1)).eq(expected) || - actual.plus(new BigNumber(2)).eq(expected) || - expected.eq(actual), - `${message} expected #{act} to be almost equal #{exp}`, - `${message} expected #{act} to be different from #{exp}`, - expected.toString(), - actual.toString() - ); -} - -export function almostEqual() { - return function (chai: any, utils: any) { - chai.Assertion.overwriteMethod('almostEqual', function (original: any) { - return function (this: any, value: any, message: string) { - if (utils.flag(this, 'bignumber')) { - var expected = new BigNumber(value); - var actual = new BigNumber(this._obj); - almostEqualAssertion.apply(this, [expected, actual, message]); - } else { - original.apply(this, arguments); - } - }; - }); - }; -} diff --git a/test/helpers/make-suite.ts b/test/helpers/make-suite.ts deleted file mode 100644 index 4a75e54d..00000000 --- a/test/helpers/make-suite.ts +++ /dev/null @@ -1,191 +0,0 @@ -import { evmRevert, evmSnapshot, DRE } from '../../helpers/misc-utils'; -import { Signer } from 'ethers'; -import { - getLendingPool, - getLendingPoolAddressesProvider, - getAaveProtocolDataProvider, - getAToken, - getMintableERC20, - getLendingPoolConfiguratorProxy, - getPriceOracle, - getLendingPoolAddressesProviderRegistry, - getWETHMocked, - getWETHGateway, - getUniswapLiquiditySwapAdapter, - getUniswapRepayAdapter, - getFlashLiquidationAdapter, -} from '../../helpers/contracts-getters'; -import { eEthereumNetwork, tEthereumAddress } from '../../helpers/types'; -import { LendingPool } from '../../types/LendingPool'; -import { AaveProtocolDataProvider } from '../../types/AaveProtocolDataProvider'; -import { MintableERC20 } from '../../types/MintableERC20'; -import { AToken } from '../../types/AToken'; -import { LendingPoolConfigurator } from '../../types/LendingPoolConfigurator'; - -import chai from 'chai'; -// @ts-ignore -import bignumberChai from 'chai-bignumber'; -import { almostEqual } from './almost-equal'; -import { PriceOracle } from '../../types/PriceOracle'; -import { LendingPoolAddressesProvider } from '../../types/LendingPoolAddressesProvider'; -import { LendingPoolAddressesProviderRegistry } from '../../types/LendingPoolAddressesProviderRegistry'; -import { getEthersSigners } from '../../helpers/contracts-helpers'; -import { UniswapLiquiditySwapAdapter } from '../../types/UniswapLiquiditySwapAdapter'; -import { UniswapRepayAdapter } from '../../types/UniswapRepayAdapter'; -import { getParamPerNetwork } from '../../helpers/contracts-helpers'; -import { WETH9Mocked } from '../../types/WETH9Mocked'; -import { WETHGateway } from '../../types/WETHGateway'; -import { solidity } from 'ethereum-waffle'; -import { AaveConfig } from '../../markets/aave'; -import { FlashLiquidationAdapter } from '../../types'; -import { HardhatRuntimeEnvironment } from 'hardhat/types'; -import { usingTenderly } from '../../helpers/tenderly-utils'; - -chai.use(bignumberChai()); -chai.use(almostEqual()); -chai.use(solidity); - -export interface SignerWithAddress { - signer: Signer; - address: tEthereumAddress; -} -export interface TestEnv { - deployer: SignerWithAddress; - users: SignerWithAddress[]; - pool: LendingPool; - configurator: LendingPoolConfigurator; - oracle: PriceOracle; - helpersContract: AaveProtocolDataProvider; - weth: WETH9Mocked; - aWETH: AToken; - dai: MintableERC20; - aDai: AToken; - usdc: MintableERC20; - aave: MintableERC20; - addressesProvider: LendingPoolAddressesProvider; - uniswapLiquiditySwapAdapter: UniswapLiquiditySwapAdapter; - uniswapRepayAdapter: UniswapRepayAdapter; - registry: LendingPoolAddressesProviderRegistry; - wethGateway: WETHGateway; - flashLiquidationAdapter: FlashLiquidationAdapter; -} - -let buidlerevmSnapshotId: string = '0x1'; -const setBuidlerevmSnapshotId = (id: string) => { - buidlerevmSnapshotId = id; -}; - -const testEnv: TestEnv = { - deployer: {} as SignerWithAddress, - users: [] as SignerWithAddress[], - pool: {} as LendingPool, - configurator: {} as LendingPoolConfigurator, - helpersContract: {} as AaveProtocolDataProvider, - oracle: {} as PriceOracle, - weth: {} as WETH9Mocked, - aWETH: {} as AToken, - dai: {} as MintableERC20, - aDai: {} as AToken, - usdc: {} as MintableERC20, - aave: {} as MintableERC20, - addressesProvider: {} as LendingPoolAddressesProvider, - uniswapLiquiditySwapAdapter: {} as UniswapLiquiditySwapAdapter, - uniswapRepayAdapter: {} as UniswapRepayAdapter, - flashLiquidationAdapter: {} as FlashLiquidationAdapter, - registry: {} as LendingPoolAddressesProviderRegistry, - wethGateway: {} as WETHGateway, -} as TestEnv; - -export async function initializeMakeSuite() { - const [_deployer, ...restSigners] = await getEthersSigners(); - const deployer: SignerWithAddress = { - address: await _deployer.getAddress(), - signer: _deployer, - }; - - for (const signer of restSigners) { - testEnv.users.push({ - signer, - address: await signer.getAddress(), - }); - } - testEnv.deployer = deployer; - testEnv.pool = await getLendingPool(); - - testEnv.configurator = await getLendingPoolConfiguratorProxy(); - - testEnv.addressesProvider = await getLendingPoolAddressesProvider(); - - if (process.env.MAINNET_FORK === 'true') { - testEnv.registry = await getLendingPoolAddressesProviderRegistry( - getParamPerNetwork(AaveConfig.ProviderRegistry, eEthereumNetwork.main) - ); - } else { - testEnv.registry = await getLendingPoolAddressesProviderRegistry(); - testEnv.oracle = await getPriceOracle(); - } - - testEnv.helpersContract = await getAaveProtocolDataProvider(); - - const allTokens = await testEnv.helpersContract.getAllATokens(); - const aDaiAddress = allTokens.find((aToken) => aToken.symbol === 'aDAI')?.tokenAddress; - - const aWEthAddress = allTokens.find((aToken) => aToken.symbol === 'aWETH')?.tokenAddress; - - const reservesTokens = await testEnv.helpersContract.getAllReservesTokens(); - - const daiAddress = reservesTokens.find((token) => token.symbol === 'DAI')?.tokenAddress; - const usdcAddress = reservesTokens.find((token) => token.symbol === 'USDC')?.tokenAddress; - const aaveAddress = reservesTokens.find((token) => token.symbol === 'AAVE')?.tokenAddress; - const wethAddress = reservesTokens.find((token) => token.symbol === 'WETH')?.tokenAddress; - - if (!aDaiAddress || !aWEthAddress) { - process.exit(1); - } - if (!daiAddress || !usdcAddress || !aaveAddress || !wethAddress) { - process.exit(1); - } - - testEnv.aDai = await getAToken(aDaiAddress); - testEnv.aWETH = await getAToken(aWEthAddress); - - testEnv.dai = await getMintableERC20(daiAddress); - testEnv.usdc = await getMintableERC20(usdcAddress); - testEnv.aave = await getMintableERC20(aaveAddress); - testEnv.weth = await getWETHMocked(wethAddress); - testEnv.wethGateway = await getWETHGateway(); - - testEnv.uniswapLiquiditySwapAdapter = await getUniswapLiquiditySwapAdapter(); - testEnv.uniswapRepayAdapter = await getUniswapRepayAdapter(); - testEnv.flashLiquidationAdapter = await getFlashLiquidationAdapter(); -} - -const setSnapshot = async () => { - const hre = DRE as HardhatRuntimeEnvironment; - if (usingTenderly()) { - setBuidlerevmSnapshotId((await hre.tenderlyRPC.getHead()) || '0x1'); - return; - } - setBuidlerevmSnapshotId(await evmSnapshot()); -}; - -const revertHead = async () => { - const hre = DRE as HardhatRuntimeEnvironment; - if (usingTenderly()) { - await hre.tenderlyRPC.setHead(buidlerevmSnapshotId); - return; - } - await evmRevert(buidlerevmSnapshotId); -}; - -export function makeSuite(name: string, tests: (testEnv: TestEnv) => void) { - describe(name, () => { - before(async () => { - await setSnapshot(); - }); - tests(testEnv); - after(async () => { - await revertHead(); - }); - }); -} diff --git a/test/helpers/scenario-engine.ts b/test/helpers/scenario-engine.ts deleted file mode 100644 index 92c686f4..00000000 --- a/test/helpers/scenario-engine.ts +++ /dev/null @@ -1,237 +0,0 @@ -import { TestEnv, SignerWithAddress } from './make-suite'; -import { - mint, - approve, - deposit, - borrow, - withdraw, - repay, - setUseAsCollateral, - swapBorrowRateMode, - rebalanceStableBorrowRate, - delegateBorrowAllowance, -} from './actions'; -import { RateMode } from '../../helpers/types'; - -export interface Action { - name: string; - args?: any; - expected: string; - revertMessage?: string; -} - -export interface Story { - description: string; - actions: Action[]; -} - -export interface Scenario { - title: string; - description: string; - stories: Story[]; -} - -export const executeStory = async (story: Story, testEnv: TestEnv) => { - for (const action of story.actions) { - const { users } = testEnv; - await executeAction(action, users, testEnv); - } -}; - -const executeAction = async (action: Action, users: SignerWithAddress[], testEnv: TestEnv) => { - const { reserve, user: userIndex, borrowRateMode } = action.args; - const { name, expected, revertMessage } = action; - - if (!name || name === '') { - throw 'Action name is missing'; - } - if (!reserve || reserve === '') { - throw 'Invalid reserve selected for deposit'; - } - if (!userIndex || userIndex === '') { - throw `Invalid user selected to deposit into the ${reserve} reserve`; - } - - if (!expected || expected === '') { - throw `An expected resut for action ${name} is required`; - } - - let rateMode: string = RateMode.None; - - if (borrowRateMode) { - if (borrowRateMode === 'none') { - rateMode = RateMode.None; - } else if (borrowRateMode === 'stable') { - rateMode = RateMode.Stable; - } else if (borrowRateMode === 'variable') { - rateMode = RateMode.Variable; - } else { - //random value, to test improper selection of the parameter - rateMode = '4'; - } - } - - const user = users[parseInt(userIndex)]; - - switch (name) { - case 'mint': - const { amount } = action.args; - - if (!amount || amount === '') { - throw `Invalid amount of ${reserve} to mint`; - } - - await mint(reserve, amount, user); - break; - - case 'approve': - await approve(reserve, user, testEnv); - break; - - case 'deposit': - { - const { amount, sendValue, onBehalfOf: onBehalfOfIndex } = action.args; - const onBehalfOf = onBehalfOfIndex - ? users[parseInt(onBehalfOfIndex)].address - : user.address; - - if (!amount || amount === '') { - throw `Invalid amount to deposit into the ${reserve} reserve`; - } - - await deposit( - reserve, - amount, - user, - onBehalfOf, - sendValue, - expected, - testEnv, - revertMessage - ); - } - break; - - case 'delegateBorrowAllowance': - { - const { amount, toUser: toUserIndex } = action.args; - const toUser = users[parseInt(toUserIndex, 10)].address; - if (!amount || amount === '') { - throw `Invalid amount to deposit into the ${reserve} reserve`; - } - - await delegateBorrowAllowance( - reserve, - amount, - rateMode, - user, - toUser, - expected, - testEnv, - revertMessage - ); - } - break; - - case 'withdraw': - { - const { amount } = action.args; - - if (!amount || amount === '') { - throw `Invalid amount to withdraw from the ${reserve} reserve`; - } - - await withdraw(reserve, amount, user, expected, testEnv, revertMessage); - } - break; - case 'borrow': - { - const { amount, timeTravel, onBehalfOf: onBehalfOfIndex } = action.args; - - const onBehalfOf = onBehalfOfIndex - ? users[parseInt(onBehalfOfIndex)].address - : user.address; - - if (!amount || amount === '') { - throw `Invalid amount to borrow from the ${reserve} reserve`; - } - - await borrow( - reserve, - amount, - rateMode, - user, - onBehalfOf, - timeTravel, - expected, - testEnv, - revertMessage - ); - } - break; - - case 'repay': - { - const { amount, borrowRateMode, sendValue } = action.args; - let { onBehalfOf: onBehalfOfIndex } = action.args; - - if (!amount || amount === '') { - throw `Invalid amount to repay into the ${reserve} reserve`; - } - - let userToRepayOnBehalf: SignerWithAddress; - if (!onBehalfOfIndex || onBehalfOfIndex === '') { - console.log( - 'WARNING: No onBehalfOf specified for a repay action. Defaulting to the repayer address' - ); - userToRepayOnBehalf = user; - } else { - userToRepayOnBehalf = users[parseInt(onBehalfOfIndex)]; - } - - await repay( - reserve, - amount, - rateMode, - user, - userToRepayOnBehalf, - sendValue, - expected, - testEnv, - revertMessage - ); - } - break; - - case 'setUseAsCollateral': - { - const { useAsCollateral } = action.args; - - if (!useAsCollateral || useAsCollateral === '') { - throw `A valid value for useAsCollateral needs to be set when calling setUseReserveAsCollateral on reserve ${reserve}`; - } - await setUseAsCollateral(reserve, user, useAsCollateral, expected, testEnv, revertMessage); - } - break; - - case 'swapBorrowRateMode': - await swapBorrowRateMode(reserve, user, rateMode, expected, testEnv, revertMessage); - break; - - case 'rebalanceStableBorrowRate': - { - const { target: targetIndex } = action.args; - - if (!targetIndex || targetIndex === '') { - throw `A target must be selected when trying to rebalance a stable rate`; - } - const target = users[parseInt(targetIndex)]; - - await rebalanceStableBorrowRate(reserve, user, target, expected, testEnv, revertMessage); - } - break; - - default: - throw `Invalid action requested: ${name}`; - } -}; diff --git a/test/helpers/scenarios/borrow-negatives.json b/test/helpers/scenarios/borrow-negatives.json deleted file mode 100644 index 03f4d005..00000000 --- a/test/helpers/scenarios/borrow-negatives.json +++ /dev/null @@ -1,142 +0,0 @@ -{ - "title": "LendingPool: Borrow negatives (reverts)", - "description": "Test cases for the deposit function.", - "stories": [ - { - "description": "User 0 deposits 1000 DAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 DAI with rate mode NONE (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "none", - "user": "1" - }, - "expected": "revert", - "revertMessage": "Invalid interest rate mode selected" - } - ] - }, - { - "description": "User 0 deposits 1000 DAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 DAI with an invalid rate mode (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "invalid", - "user": "1" - }, - "expected": "revert", - "revertMessage": "Invalid interest rate mode selected" - } - ] - } - ] -} diff --git a/test/helpers/scenarios/borrow-repay-stable.json b/test/helpers/scenarios/borrow-repay-stable.json deleted file mode 100644 index bdbf1aff..00000000 --- a/test/helpers/scenarios/borrow-repay-stable.json +++ /dev/null @@ -1,656 +0,0 @@ -{ - "title": "LendingPool: Borrow/repay (stable rate)", - "description": "Test cases for the borrow function, stable mode.", - "stories": [ - { - "description": "User 0 deposits 1000 DAI, user 1 deposits 1 WETH as collateral and borrows 100 DAI at stable rate", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "stable", - "user": "1", - "timeTravel": "365" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 tries to borrow the rest of the DAI liquidity (revert expected)", - "actions": [ - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "900", - "borrowRateMode": "stable", - "user": "1" - }, - "expected": "revert", - "revertMessage": "There is not enough collateral to cover a new borrow" - } - ] - }, - { - "description": "User 1 repays half of the DAI borrow after one year", - "actions": [ - { - "name": "mint", - "description": "Mint 10 DAI to cover the interest", - "args": { - "reserve": "DAI", - "amount": "10", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "1" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "50", - "user": "1", - "onBehalfOf": "1", - "borrowRateMode": "stable" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 repays the rest of the DAI borrow after one year", - "actions": [ - { - "name": "mint", - "description": "Mint 15 DAI to cover the interest", - "args": { - "reserve": "DAI", - "amount": "15", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "1" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "1", - "onBehalfOf": "1", - "borrowRateMode": "stable" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 withdraws the deposited DAI plus interest", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 deposits 1000 DAI, user 2 tries to borrow 1000 DAI at a stable rate without any collateral (revert expected) User 1 withdrawws", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "1000", - "borrowRateMode": "stable", - "user": "2" - }, - "expected": "revert", - "revertMessage": "The collateral balance is 0" - }, - { - "name": "withdraw", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "1" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 deposits 1000 DAI, user 1,2,3,4 deposit 1 WETH each and borrow 100 DAI at stable rate. Everything is repaid, user 0 withdraws", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "stable", - "user": "1", - "timeTravel": "365" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "2" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "2" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "2" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "stable", - "user": "2", - "timeTravel": "365" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "3" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "3" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "3" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "stable", - "user": "3", - "timeTravel": "365" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "4" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "4" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "4" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "stable", - "user": "4", - "timeTravel": "365" - }, - "expected": "success" - }, - { - "name": "mint", - "description": "Mint 15 DAI to cover the interest", - "args": { - "reserve": "DAI", - "amount": "15", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "1" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "1", - "onBehalfOf": "1", - "borrowRateMode": "stable" - }, - "expected": "success" - }, - { - "name": "mint", - "description": "Mint 20 DAI to cover the interest", - "args": { - "reserve": "DAI", - "amount": "20", - "user": "2" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "2" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "2", - "onBehalfOf": "2", - "borrowRateMode": "stable" - }, - "expected": "success" - }, - { - "name": "mint", - "description": "Mint 30 DAI to cover the interest", - "args": { - "reserve": "DAI", - "amount": "30", - "user": "3" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "3" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "3", - "onBehalfOf": "3", - "borrowRateMode": "stable" - }, - "expected": "success" - }, - { - "name": "mint", - "description": "Mint 30 DAI to cover the interest", - "args": { - "reserve": "DAI", - "amount": "30", - "user": "4" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "4" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "4", - "onBehalfOf": "4", - "borrowRateMode": "stable" - }, - "expected": "success" - }, - { - "name": "withdraw", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 deposits 1000 DAI, user 1 deposits 2 WETH and borrow 100 DAI at stable rate first, then 100 DAI at variable rate, repays everything. User 0 withdraws", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "2", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "2", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "stable", - "user": "1", - "timeTravel": "365" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "variable", - "user": "1", - "timeTravel": "365" - }, - "expected": "success" - }, - { - "name": "mint", - "description": "Mint 50 DAI to cover the interest", - "args": { - "reserve": "DAI", - "amount": "50", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "1" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "1", - "onBehalfOf": "1", - "borrowRateMode": "stable" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "1", - "onBehalfOf": "1", - "borrowRateMode": "variable" - }, - "expected": "success" - }, - { - "name": "withdraw", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "0" - }, - "expected": "success" - } - ] - } - ] -} diff --git a/test/helpers/scenarios/borrow-repay-variable.json b/test/helpers/scenarios/borrow-repay-variable.json deleted file mode 100644 index 3c4ce368..00000000 --- a/test/helpers/scenarios/borrow-repay-variable.json +++ /dev/null @@ -1,945 +0,0 @@ -{ - "title": "LendingPool: Borrow/repay (variable rate)", - "description": "Test cases for the borrow function, variable mode.", - "stories": [ - { - "description": "User 2 deposits 1 DAI to account for rounding errors", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1", - "user": "2" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "2" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1", - "user": "2" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 deposits 1000 DAI, user 1 deposits 1 WETH as collateral and borrows 100 DAI at variable rate", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "variable", - "user": "1", - "timeTravel": "365" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 tries to borrow the rest of the DAI liquidity (revert expected)", - "actions": [ - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "900", - "borrowRateMode": "variable", - "user": "1" - }, - "expected": "revert", - "revertMessage": "There is not enough collateral to cover a new borrow" - } - ] - }, - { - "description": "User 1 tries to repay 0 DAI (revert expected)", - "actions": [ - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "0", - "user": "1", - "onBehalfOf": "1" - }, - "expected": "revert", - "revertMessage": "Amount must be greater than 0" - } - ] - }, - { - "description": "User 1 repays a small amount of DAI, enough to cover a small part of the interest", - "actions": [ - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "1" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "1.25", - "user": "1", - "onBehalfOf": "1", - "borrowRateMode": "variable" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 repays the DAI borrow after one year", - "actions": [ - { - "name": "mint", - "description": "Mint 10 DAI to cover the interest", - "args": { - "reserve": "DAI", - "amount": "10", - "user": "1" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "1", - "onBehalfOf": "1", - "borrowRateMode": "variable" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 withdraws the deposited DAI plus interest", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 withdraws the collateral", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "WETH", - "amount": "-1", - "user": "1" - }, - "expected": "success" - } - ] - }, - { - "description": "User 2 deposits a small amount of WETH to account for rounding errors", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "0.001", - "user": "2" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "2" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "0.001", - "user": "2" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 deposits 1 WETH, user 1 deposits 100 LINK as collateral and borrows 0.5 ETH at variable rate", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "0" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "LINK", - "amount": "100", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "LINK", - "user": "1" - }, - "expected": "success" - }, - - { - "name": "deposit", - "args": { - "reserve": "LINK", - "amount": "100", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "WETH", - "amount": "0.5", - "borrowRateMode": "variable", - "user": "1", - "timeTravel": "365" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 tries to repay 0 ETH", - "actions": [ - { - "name": "repay", - "args": { - "reserve": "WETH", - "amount": "0", - "user": "1", - "onBehalfOf": "1", - "borrowRateMode": "variable" - }, - "expected": "revert", - "revertMessage": "Amount must be greater than 0" - } - ] - }, - { - "description": "User 2 tries to repay everything on behalf of user 1 using uint(-1) (revert expected)", - "actions": [ - { - "name": "repay", - "args": { - "reserve": "WETH", - "amount": "-1", - "user": "2", - "borrowRateMode": "variable", - "onBehalfOf": "1" - }, - "expected": "revert", - "revertMessage": "To repay on behalf of an user an explicit amount to repay is needed" - } - ] - }, - { - "description": "User 3 repays a small amount of WETH on behalf of user 1", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "3" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "3" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "WETH", - "amount": "0.2", - "user": "3", - "borrowRateMode": "variable", - "onBehalfOf": "1" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 repays the WETH borrow after one year", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "2" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "2" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "WETH", - "amount": "-1", - "borrowRateMode": "variable", - "user": "1", - "onBehalfOf": "1" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 withdraws the deposited WETH plus interest", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "WETH", - "amount": "-1", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 withdraws the collateral", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "LINK", - "amount": "-1", - "user": "1" - }, - "expected": "success" - } - ] - }, - - { - "description": "User 2 deposits 1 USDC to account for rounding errors", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "USDC", - "amount": "1", - "user": "2" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "USDC", - "user": "2" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "USDC", - "amount": "1", - "user": "2" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 deposits 1000 USDC, user 1 deposits 1 WETH as collateral and borrows 100 USDC at variable rate", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "USDC", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "USDC", - "amount": "100", - "borrowRateMode": "variable", - "user": "1", - "timeTravel": "365" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 tries to borrow the rest of the USDC liquidity (revert expected)", - "actions": [ - { - "name": "borrow", - "args": { - "reserve": "USDC", - "amount": "900", - "borrowRateMode": "variable", - "user": "1" - }, - "expected": "revert", - "revertMessage": "There is not enough collateral to cover a new borrow" - } - ] - }, - { - "description": "User 1 repays the USDC borrow after one year", - "actions": [ - { - "name": "mint", - "description": "Mint 10 USDC to cover the interest", - "args": { - "reserve": "USDC", - "amount": "10", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "USDC", - "user": "1" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "USDC", - "amount": "-1", - "user": "1", - "onBehalfOf": "1", - "borrowRateMode": "variable" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 withdraws the deposited USDC plus interest", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "USDC", - "amount": "-1", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 withdraws the collateral", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "WETH", - "amount": "-1", - "user": "1" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 deposits 1000 DAI, user 3 tries to borrow 1000 DAI without any collateral (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "1000", - "borrowRateMode": "variable", - "user": "3" - }, - "expected": "revert", - "revertMessage": "The collateral balance is 0" - } - ] - }, - { - "description": "user 3 deposits 0.1 ETH collateral to borrow 100 DAI; 0.1 ETH is not enough to borrow 100 DAI (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "0.1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "0.1", - "user": "3" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "variable", - "user": "3" - }, - "expected": "revert", - "revertMessage": "There is not enough collateral to cover a new borrow" - } - ] - }, - { - "description": "user 3 withdraws the 0.1 ETH", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "WETH", - "amount": "-1", - "user": "3" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 deposits 1000 USDC, user 3 tries to borrow 1000 USDC without any collateral (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "USDC", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "USDC", - "amount": "1000", - "borrowRateMode": "variable", - "user": "3" - }, - "expected": "revert", - "revertMessage": "The collateral balance is 0" - } - ] - }, - { - "description": "user 3 deposits 0.1 ETH collateral to borrow 100 USDC; 0.1 ETH is not enough to borrow 100 USDC (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "3" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "0.1", - "user": "3" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "USDC", - "amount": "100", - "borrowRateMode": "variable", - "user": "3" - }, - "expected": "revert", - "revertMessage": "There is not enough collateral to cover a new borrow" - } - ] - }, - { - "description": "user 3 withdraws the 0.1 ETH", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "WETH", - "amount": "-1", - "user": "3" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 deposits 1000 DAI, user 6 deposits 2 WETH and borrow 100 DAI at variable rate first, then 100 DAI at stable rate, repays everything. User 0 withdraws", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "2", - "user": "6" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "6" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "2", - "user": "6" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "variable", - "user": "6", - "timeTravel": "365" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "stable", - "user": "6", - "timeTravel": "365" - }, - "expected": "success" - }, - { - "name": "mint", - "description": "Mint 50 DAI to cover the interest", - "args": { - "reserve": "DAI", - "amount": "50", - "user": "6" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "6" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "6", - "onBehalfOf": "6", - "borrowRateMode": "stable" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "6", - "onBehalfOf": "6", - "borrowRateMode": "variable" - }, - "expected": "success" - }, - { - "name": "withdraw", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "0" - }, - "expected": "success" - } - ] - } - ] -} diff --git a/test/helpers/scenarios/credit-delegation.json b/test/helpers/scenarios/credit-delegation.json deleted file mode 100644 index 2efabeb1..00000000 --- a/test/helpers/scenarios/credit-delegation.json +++ /dev/null @@ -1,157 +0,0 @@ -{ - "title": "LendingPool: credit delegation", - "description": "Test cases for the credit delegation related functions.", - "stories": [ - { - "description": "User 3 deposits 1000 WETH. User 0 deposits 1000 DAI, user 0 delegates borrowing of 1 WETH on variable to user 4, user 4 borrows 1 WETH variable on behalf of user 0", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1000", - "user": "3" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "3" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1000", - "user": "3" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "delegateBorrowAllowance", - "args": { - "reserve": "WETH", - "amount": "2", - "user": "0", - "borrowRateMode": "variable", - "toUser": "4" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "4", - "onBehalfOf": "0", - "borrowRateMode": "variable" - }, - "expected": "success" - } - ] - }, - { - "description": "User 4 trying to borrow 1 WETH stable on behalf of user 0, revert expected", - "actions": [ - { - "name": "borrow", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "4", - "onBehalfOf": "0", - "borrowRateMode": "stable" - }, - "expected": "revert", - "revertMessage": "59" - } - ] - }, - { - "description": "User 0 delegates borrowing of 1 WETH to user 4, user 4 borrows 3 WETH variable on behalf of user 0, revert expected", - "actions": [ - { - "name": "delegateBorrowAllowance", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "0", - "borrowRateMode": "variable", - "toUser": "4" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "WETH", - "amount": "3", - "user": "4", - "onBehalfOf": "0", - "borrowRateMode": "variable" - }, - "expected": "revert", - "revertMessage": "59" - } - ] - }, - { - "description": "User 0 delegates borrowing of 1 WETH on stable to user 2, user 2 borrows 1 WETH stable on behalf of user 0", - "actions": [ - { - "name": "delegateBorrowAllowance", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "0", - "borrowRateMode": "stable", - "toUser": "2" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "2", - "onBehalfOf": "0", - "borrowRateMode": "stable" - }, - "expected": "success" - } - ] - } - ] -} diff --git a/test/helpers/scenarios/deposit.json b/test/helpers/scenarios/deposit.json deleted file mode 100644 index b4b73879..00000000 --- a/test/helpers/scenarios/deposit.json +++ /dev/null @@ -1,266 +0,0 @@ -{ - "title": "LendingPool: Deposit", - "description": "Test cases for the deposit function.", - "stories": [ - { - "description": "User 0 Deposits 1000 DAI in an empty reserve", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 deposits 1000 DAI after user 0", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "1" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 deposits 1000 USDC in an empty reserve", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "USDC", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 deposits 1000 USDC after user 0", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "USDC", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "1" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 deposits 1 WETH in an empty reserve", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 deposits 1 WETH after user 0", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 deposits 0 WETH (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "0", - "user": "1" - }, - "expected": "revert", - "revertMessage": "Amount must be greater than 0" - } - ] - }, - { - "description": "User 1 deposits 0 DAI", - "actions": [ - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "0", - "user": "1" - }, - "expected": "revert", - "revertMessage": "Amount must be greater than 0" - } - ] - }, - { - "description": "User 1 deposits 100 DAI on behalf of user 2, user 2 tries to borrow 0.1 WETH", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "100", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "100", - "user": "1", - "onBehalfOf": "2" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "WETH", - "amount": "0.1", - "borrowRateMode": "variable", - "user": "2" - }, - "expected": "success" - } - ] - } - ] -} diff --git a/test/helpers/scenarios/rebalance-stable-rate.json b/test/helpers/scenarios/rebalance-stable-rate.json deleted file mode 100644 index 79c224f8..00000000 --- a/test/helpers/scenarios/rebalance-stable-rate.json +++ /dev/null @@ -1,198 +0,0 @@ -{ - "title": "LendingPool: Rebalance stable rate", - "description": "Test cases for the rebalanceStableBorrowRate() function.", - "stories": [ - { - "description": "User 0 tries to rebalance user 1 who has no borrows in progress (revert expected)", - "actions": [ - { - "name": "rebalanceStableBorrowRate", - "args": { - "reserve": "USDC", - "user": "0", - "target": "1" - }, - "expected": "revert", - "revertMessage": "User does not have any stable rate loan for this reserve" - } - ] - }, - { - "description": "User 0 deposits 1000 USDC, user 1 deposits 7 WETH, borrows 250 USDC at a stable rate, user 0 rebalances user 1 (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "USDC", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "7", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "7", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "USDC", - "amount": "250", - "borrowRateMode": "stable", - "user": "1" - }, - "expected": "success" - }, - { - "name": "rebalanceStableBorrowRate", - "args": { - "reserve": "USDC", - "user": "0", - "target": "1" - }, - "expected": "revert", - "revertMessage": "The user borrow is variable and cannot be rebalanced" - } - ] - }, - { - "description": "User 1 borrows another 200 at variable, user 0 tries to rebalance but the conditions are not met (revert expected)", - "actions": [ - { - "name": "borrow", - "args": { - "reserve": "USDC", - "amount": "200", - "borrowRateMode": "variable", - "user": "1" - }, - "expected": "success" - }, - { - "name": "rebalanceStableBorrowRate", - "args": { - "reserve": "USDC", - "user": "0", - "target": "1" - }, - "expected": "revert", - "revertMessage": "Interest rate rebalance conditions were not met" - } - ] - }, - { - "description": "User 1 borrows another 200 at variable, user 0 tries to rebalance but the conditions are not met (revert expected)", - "actions": [ - { - "name": "borrow", - "args": { - "reserve": "USDC", - "amount": "200", - "borrowRateMode": "variable", - "user": "1" - }, - "expected": "success" - }, - { - "name": "rebalanceStableBorrowRate", - "args": { - "reserve": "USDC", - "user": "0", - "target": "1" - }, - "expected": "revert", - "revertMessage": "Interest rate rebalance conditions were not met" - } - ] - }, - { - "description": "User 1 borrows another 100 at variable, user 0 tries to rebalance but the conditions are not met (revert expected)", - "actions": [ - { - "name": "borrow", - "args": { - "reserve": "USDC", - "amount": "280", - "borrowRateMode": "variable", - "user": "1" - }, - "expected": "success" - }, - { - "name": "rebalanceStableBorrowRate", - "args": { - "reserve": "USDC", - "user": "0", - "target": "1" - }, - "expected": "revert", - "revertMessage": "Interest rate rebalance conditions were not met" - } - ] - }, - - { - "description": "User 1 borrows the remaining USDC (usage ratio = 100%) at variable. User 0 rebalances user 1", - "actions": [ - { - "name": "borrow", - "args": { - "reserve": "USDC", - "amount": "20", - "borrowRateMode": "variable", - "user": "1" - }, - "expected": "success" - }, - { - "name": "rebalanceStableBorrowRate", - "args": { - "reserve": "USDC", - "user": "0", - "target": "1" - }, - "expected": "success" - } - ] - } - ] -} diff --git a/test/helpers/scenarios/set-use-as-collateral.json b/test/helpers/scenarios/set-use-as-collateral.json deleted file mode 100644 index 2a206bb9..00000000 --- a/test/helpers/scenarios/set-use-as-collateral.json +++ /dev/null @@ -1,236 +0,0 @@ -{ - "title": "LendingPool: Usage as collateral", - "description": "Test cases for the setUserUseReserveAsCollateral() function.", - "stories": [ - { - "description": "User 0 Deposits 1000 DAI, disables DAI as collateral", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "setUseAsCollateral", - "args": { - "reserve": "DAI", - "user": "0", - "useAsCollateral": "false" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 Deposits 2 WETH, disables WETH as collateral, borrows 400 DAI (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "2", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "2", - "user": "1" - }, - "expected": "success" - }, - { - "name": "setUseAsCollateral", - "args": { - "reserve": "WETH", - "user": "1", - "useAsCollateral": "false" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "400", - "borrowRateMode": "variable", - "user": "1" - }, - "expected": "revert", - "revertMessage": "The collateral balance is 0" - } - ] - }, - { - "description": "User 1 enables WETH as collateral, borrows 400 DAI", - "actions": [ - { - "name": "setUseAsCollateral", - "args": { - "reserve": "WETH", - "user": "1", - "useAsCollateral": "true" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "400", - "borrowRateMode": "variable", - "user": "1" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 disables WETH as collateral (revert expected)", - "actions": [ - { - "name": "setUseAsCollateral", - "args": { - "reserve": "WETH", - "user": "1", - "useAsCollateral": "false" - }, - "expected": "revert", - "revertMessage": "User deposit is already being used as collateral" - } - ] - }, - { - "description": "User 1 Deposits 10 AAVE, disables WETH as collateral. Should revert as 10 AAVE are not enough to cover the debt (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "AAVE", - "amount": "10", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "AAVE", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "AAVE", - "amount": "10", - "user": "1" - }, - "expected": "success" - }, - { - "name": "setUseAsCollateral", - "args": { - "reserve": "WETH", - "user": "1", - "useAsCollateral": "false" - }, - "expected": "revert" - } - ] - }, - { - "description": "User 1 Deposits 640 more AAVE (enough to cover the DAI debt), disables WETH as collateral", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "AAVE", - "amount": "640", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "AAVE", - "amount": "640", - "user": "1" - }, - "expected": "success" - }, - { - "name": "setUseAsCollateral", - "args": { - "reserve": "WETH", - "user": "1", - "useAsCollateral": "false" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 disables AAVE as collateral (revert expected)", - "actions": [ - { - "name": "setUseAsCollateral", - "args": { - "reserve": "AAVE", - "user": "1", - "useAsCollateral": "false" - }, - "expected": "revert" - } - ] - }, - { - "description": "User 1 reenables WETH as collateral", - "actions": [ - { - "name": "setUseAsCollateral", - "args": { - "reserve": "WETH", - "user": "1", - "useAsCollateral": "true" - }, - "expected": "success" - } - ] - } - ] -} diff --git a/test/helpers/scenarios/swap-rate-mode.json b/test/helpers/scenarios/swap-rate-mode.json deleted file mode 100644 index e966af9a..00000000 --- a/test/helpers/scenarios/swap-rate-mode.json +++ /dev/null @@ -1,167 +0,0 @@ -{ - "title": "LendingPool: Swap rate mode", - "description": "Test cases for the swapBorrowRateMode() function.", - "stories": [ - { - "description": "User 0 tries to swap rate mode without any variable rate loan in progress (revert expected)", - "actions": [ - { - "name": "swapBorrowRateMode", - "args": { - "reserve": "DAI", - "user": "1", - "borrowRateMode": "variable" - }, - "expected": "revert", - "revertMessage": "User does not have a variable rate loan in progress on this reserve" - } - ] - }, - { - "description": "User 0 tries to swap rate mode without any stable rate loan in progress (revert expected)", - "actions": [ - { - "name": "swapBorrowRateMode", - "args": { - "reserve": "DAI", - "user": "1", - "borrowRateMode": "stable" - }, - "expected": "revert", - "revertMessage": "User does not have a stable rate loan in progress on this reserve" - } - ] - }, - { - "description": "User 0 deposits 1000 DAI, user 1 deposits 2 ETH as collateral, borrows 100 DAI at variable rate and swaps to stable after one year", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "2", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "2", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "variable", - "user": "1", - "timeTravel": "365" - }, - "expected": "success" - }, - { - "name": "swapBorrowRateMode", - "args": { - "reserve": "DAI", - "user": "1", - "borrowRateMode": "variable" - }, - "expected": "success" - } - ] - }, - { - "description": "User 1 borrows another 100 DAI, and swaps back to variable after one year, repays the loan", - "actions": [ - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "borrowRateMode": "stable", - "user": "1", - "timeTravel": "365" - }, - "expected": "success" - }, - { - "name": "swapBorrowRateMode", - "args": { - "reserve": "DAI", - "user": "1", - "borrowRateMode": "stable" - }, - "expected": "success" - }, - { - "name": "mint", - "description": "Mint 50 DAI to cover the interest", - "args": { - "reserve": "DAI", - "amount": "50", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "1" - }, - "expected": "success" - }, - { - "name": "repay", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "1", - "onBehalfOf": "1", - "borrowRateMode": "variable" - }, - "expected": "success" - } - ] - } - ] -} diff --git a/test/helpers/scenarios/withdraw-negatives.json b/test/helpers/scenarios/withdraw-negatives.json deleted file mode 100644 index fbc5c308..00000000 --- a/test/helpers/scenarios/withdraw-negatives.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "title": "LendingPool: Redeem negative test cases", - "description": "Redeem function.", - "stories": [ - { - "description": "Users 0 Deposits 1000 DAI and tries to redeem 0 DAI (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - - { - "name": "withdraw", - "args": { - "reserve": "DAI", - "amount": "0", - "user": "0" - }, - "expected": "revert", - "revertMessage": "Amount to redeem needs to be > 0" - } - ] - }, - { - "description": "Users 0 tries to redeem 1100 DAI from the 1000 DAI deposited (revert expected)", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "DAI", - "amount": "1100", - "user": "0" - }, - "expected": "revert", - "revertMessage": "User cannot redeem more than the available balance" - } - ] - }, - { - "description": "Users 1 deposits 1 WETH, borrows 100 DAI, tries to redeem the 1 WETH deposited (revert expected)", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "user": "1", - "borrowRateMode": "stable" - }, - "expected": "success" - }, - { - "name": "withdraw", - "args": { - "reserve": "WETH", - "amount": "-1", - "user": "1" - }, - "expected": "revert", - "revertMessage": "Transfer cannot be allowed." - } - ] - } - ] -} diff --git a/test/helpers/scenarios/withdraw.json b/test/helpers/scenarios/withdraw.json deleted file mode 100644 index 5f183eca..00000000 --- a/test/helpers/scenarios/withdraw.json +++ /dev/null @@ -1,340 +0,0 @@ -{ - "title": "LendingPool: withdraw", - "description": "withdraw function.", - "stories": [ - { - "description": "User 0 Deposits 1000 DAI in an empty reserve", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 withdraws half of the deposited DAI", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "DAI", - "amount": "500", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 withdraws remaining half of the deposited DAI", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 Deposits 1000 USDC in an empty reserve", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "USDC", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 withdraws half of the deposited USDC", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "USDC", - "amount": "500", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 withdraws remaining half of the deposited USDC", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "USDC", - "amount": "-1", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 Deposits 1 WETH in an empty reserve", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "0" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 withdraws half of the deposited WETH", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "WETH", - "amount": "0.5", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "User 0 withdraws remaining half of the deposited ETH", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "WETH", - "amount": "-1", - "user": "0" - }, - "expected": "success" - } - ] - }, - { - "description": "Users 0 and 1 Deposit 1000 DAI, both withdraw", - "actions": [ - { - "name": "mint", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "DAI", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "withdraw", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "0" - }, - "expected": "success" - }, - { - "name": "withdraw", - "args": { - "reserve": "DAI", - "amount": "-1", - "user": "1" - }, - "expected": "success" - } - ] - }, - { - "description": "Users 0 deposits 1000 DAI, user 1 Deposit 1000 USDC and 1 WETH, borrows 100 DAI. User 1 tries to withdraw all the USDC", - "actions": [ - { - "name": "deposit", - "args": { - "reserve": "DAI", - "amount": "1000", - "user": "0" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "USDC", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "USDC", - "amount": "1000", - "user": "1" - }, - "expected": "success" - }, - { - "name": "mint", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "approve", - "args": { - "reserve": "WETH", - "user": "1" - }, - "expected": "success" - }, - { - "name": "deposit", - "args": { - "reserve": "WETH", - "amount": "1", - "user": "1" - }, - "expected": "success" - }, - { - "name": "borrow", - "args": { - "reserve": "DAI", - "amount": "100", - "user": "1", - "borrowRateMode": "stable" - }, - "expected": "success" - }, - { - "name": "withdraw", - "args": { - "reserve": "USDC", - "amount": "-1", - "user": "1" - }, - "expected": "success" - } - ] - }, - { - "description": "Users 1 tries to withdraw 0.05 WETH, which does not bring the HF below 1", - "actions": [ - { - "name": "withdraw", - "args": { - "reserve": "WETH", - "amount": "0.05", - "user": "1" - }, - "expected": "success" - } - ] - } - ] -} diff --git a/test/helpers/utils/calculations.ts b/test/helpers/utils/calculations.ts deleted file mode 100644 index aeb9d74e..00000000 --- a/test/helpers/utils/calculations.ts +++ /dev/null @@ -1,1434 +0,0 @@ -import BigNumber from 'bignumber.js'; -import { ONE_YEAR, RAY, MAX_UINT_AMOUNT, PERCENTAGE_FACTOR } from '../../../helpers/constants'; -import { - IReserveParams, - iAavePoolAssets, - RateMode, - tEthereumAddress, -} from '../../../helpers/types'; -import './math'; -import { ReserveData, UserReserveData } from './interfaces'; - -export const strToBN = (amount: string): BigNumber => new BigNumber(amount); - -interface Configuration { - reservesParams: iAavePoolAssets; -} - -export const configuration: Configuration = {}; - -export const calcExpectedUserDataAfterDeposit = ( - amountDeposited: string, - reserveDataBeforeAction: ReserveData, - reserveDataAfterAction: ReserveData, - userDataBeforeAction: UserReserveData, - txTimestamp: BigNumber, - currentTimestamp: BigNumber, - txCost: BigNumber -): UserReserveData => { - const expectedUserData = {}; - - expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance( - userDataBeforeAction.principalStableDebt, - userDataBeforeAction.stableBorrowRate, - userDataBeforeAction.stableRateLastUpdated, - txTimestamp - ); - - expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ); - - expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; - expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt; - expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; - expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; - expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated; - - expectedUserData.liquidityRate = reserveDataAfterAction.liquidityRate; - - expectedUserData.scaledATokenBalance = calcExpectedScaledATokenBalance( - userDataBeforeAction, - reserveDataAfterAction.liquidityIndex, - new BigNumber(amountDeposited), - new BigNumber(0) - ); - expectedUserData.currentATokenBalance = calcExpectedATokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ).plus(amountDeposited); - - if (userDataBeforeAction.currentATokenBalance.eq(0)) { - expectedUserData.usageAsCollateralEnabled = true; - } else { - expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled; - } - - expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; - expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(amountDeposited); - - expectedUserData.currentStableDebt = expectedUserData.principalStableDebt = calcExpectedStableDebtTokenBalance( - userDataBeforeAction.principalStableDebt, - userDataBeforeAction.stableBorrowRate, - userDataBeforeAction.stableRateLastUpdated, - txTimestamp - ); - - expectedUserData.currentVariableDebt = expectedUserData.principalStableDebt = calcExpectedVariableDebtTokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ); - - return expectedUserData; -}; - -export const calcExpectedUserDataAfterWithdraw = ( - amountWithdrawn: string, - reserveDataBeforeAction: ReserveData, - reserveDataAfterAction: ReserveData, - userDataBeforeAction: UserReserveData, - txTimestamp: BigNumber, - currentTimestamp: BigNumber, - txCost: BigNumber -): UserReserveData => { - const expectedUserData = {}; - - const aTokenBalance = calcExpectedATokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ); - - if (amountWithdrawn == MAX_UINT_AMOUNT) { - amountWithdrawn = aTokenBalance.toFixed(0); - } - - expectedUserData.scaledATokenBalance = calcExpectedScaledATokenBalance( - userDataBeforeAction, - reserveDataAfterAction.liquidityIndex, - new BigNumber(0), - new BigNumber(amountWithdrawn) - ); - - expectedUserData.currentATokenBalance = aTokenBalance.minus(amountWithdrawn); - - expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; - expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt; - - expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance( - userDataBeforeAction.principalStableDebt, - userDataBeforeAction.stableBorrowRate, - userDataBeforeAction.stableRateLastUpdated, - txTimestamp - ); - - expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ); - - expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; - expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; - expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated; - - expectedUserData.liquidityRate = reserveDataAfterAction.liquidityRate; - - if (userDataBeforeAction.currentATokenBalance.eq(0)) { - expectedUserData.usageAsCollateralEnabled = true; - } else { - //if the user is withdrawing everything, usageAsCollateralEnabled must be false - if (expectedUserData.currentATokenBalance.eq(0)) { - expectedUserData.usageAsCollateralEnabled = false; - } else { - expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled; - } - } - - expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountWithdrawn); - - return expectedUserData; -}; - -export const calcExpectedReserveDataAfterDeposit = ( - amountDeposited: string, - reserveDataBeforeAction: ReserveData, - txTimestamp: BigNumber -): ReserveData => { - const expectedReserveData: ReserveData = {}; - - expectedReserveData.address = reserveDataBeforeAction.address; - - expectedReserveData.totalLiquidity = new BigNumber(reserveDataBeforeAction.totalLiquidity).plus( - amountDeposited - ); - expectedReserveData.availableLiquidity = new BigNumber( - reserveDataBeforeAction.availableLiquidity - ).plus(amountDeposited); - - expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate; - expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( - reserveDataBeforeAction, - txTimestamp - ); - expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( - reserveDataBeforeAction, - txTimestamp - ); - - expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( - reserveDataBeforeAction.principalStableDebt, - reserveDataBeforeAction.averageStableBorrowRate, - reserveDataBeforeAction.totalStableDebtLastUpdated, - txTimestamp - ); - expectedReserveData.totalVariableDebt = calcExpectedTotalVariableDebt( - reserveDataBeforeAction, - expectedReserveData.variableBorrowIndex - ); - - expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; - expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt; - - expectedReserveData.utilizationRate = calcExpectedUtilizationRate( - expectedReserveData.totalStableDebt, - expectedReserveData.totalVariableDebt, - expectedReserveData.totalLiquidity - ); - const rates = calcExpectedInterestRates( - reserveDataBeforeAction.symbol, - reserveDataBeforeAction.marketStableRate, - expectedReserveData.utilizationRate, - expectedReserveData.totalStableDebt, - expectedReserveData.totalVariableDebt, - expectedReserveData.averageStableBorrowRate - ); - expectedReserveData.liquidityRate = rates[0]; - expectedReserveData.stableBorrowRate = rates[1]; - expectedReserveData.variableBorrowRate = rates[2]; - - return expectedReserveData; -}; - -export const calcExpectedReserveDataAfterWithdraw = ( - amountWithdrawn: string, - reserveDataBeforeAction: ReserveData, - userDataBeforeAction: UserReserveData, - txTimestamp: BigNumber -): ReserveData => { - const expectedReserveData: ReserveData = {}; - - expectedReserveData.address = reserveDataBeforeAction.address; - - if (amountWithdrawn == MAX_UINT_AMOUNT) { - amountWithdrawn = calcExpectedATokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ).toFixed(); - } - - expectedReserveData.availableLiquidity = new BigNumber( - reserveDataBeforeAction.availableLiquidity - ).minus(amountWithdrawn); - - expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt; - expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; - - expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( - reserveDataBeforeAction, - txTimestamp - ); - expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( - reserveDataBeforeAction, - txTimestamp - ); - - expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( - reserveDataBeforeAction.principalStableDebt, - reserveDataBeforeAction.averageStableBorrowRate, - reserveDataBeforeAction.totalStableDebtLastUpdated, - txTimestamp - ); - expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( - expectedReserveData.variableBorrowIndex - ); - - expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate; - - expectedReserveData.totalLiquidity = new BigNumber(reserveDataBeforeAction.availableLiquidity) - .minus(amountWithdrawn) - .plus(expectedReserveData.totalVariableDebt) - .plus(expectedReserveData.totalStableDebt); - - expectedReserveData.utilizationRate = calcExpectedUtilizationRate( - expectedReserveData.totalStableDebt, - expectedReserveData.totalVariableDebt, - expectedReserveData.totalLiquidity - ); - const rates = calcExpectedInterestRates( - reserveDataBeforeAction.symbol, - reserveDataBeforeAction.marketStableRate, - expectedReserveData.utilizationRate, - expectedReserveData.totalStableDebt, - expectedReserveData.totalVariableDebt, - expectedReserveData.averageStableBorrowRate - ); - expectedReserveData.liquidityRate = rates[0]; - expectedReserveData.stableBorrowRate = rates[1]; - expectedReserveData.variableBorrowRate = rates[2]; - - return expectedReserveData; -}; - -export const calcExpectedReserveDataAfterBorrow = ( - amountBorrowed: string, - borrowRateMode: string, - reserveDataBeforeAction: ReserveData, - userDataBeforeAction: UserReserveData, - txTimestamp: BigNumber, - currentTimestamp: BigNumber -): ReserveData => { - const expectedReserveData = {}; - - expectedReserveData.address = reserveDataBeforeAction.address; - - const amountBorrowedBN = new BigNumber(amountBorrowed); - - expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( - reserveDataBeforeAction, - txTimestamp - ); - - expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( - reserveDataBeforeAction, - txTimestamp - ); - - expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity.minus( - amountBorrowedBN - ); - - expectedReserveData.lastUpdateTimestamp = txTimestamp; - - if (borrowRateMode == RateMode.Stable) { - expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; - - const expectedVariableDebtAfterTx = expectedReserveData.scaledVariableDebt.rayMul( - expectedReserveData.variableBorrowIndex - ); - - const expectedStableDebtUntilTx = calcExpectedTotalStableDebt( - reserveDataBeforeAction.principalStableDebt, - reserveDataBeforeAction.averageStableBorrowRate, - reserveDataBeforeAction.totalStableDebtLastUpdated, - txTimestamp - ); - - expectedReserveData.principalStableDebt = expectedStableDebtUntilTx.plus(amountBorrowedBN); - - expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( - reserveDataBeforeAction.averageStableBorrowRate, - expectedStableDebtUntilTx, - amountBorrowedBN, - reserveDataBeforeAction.stableBorrowRate - ); - - const totalLiquidityAfterTx = expectedReserveData.availableLiquidity - .plus(expectedReserveData.principalStableDebt) - .plus(expectedVariableDebtAfterTx); - - const utilizationRateAfterTx = calcExpectedUtilizationRate( - expectedReserveData.principalStableDebt, //the expected principal debt is the total debt immediately after the tx - expectedVariableDebtAfterTx, - totalLiquidityAfterTx - ); - - const ratesAfterTx = calcExpectedInterestRates( - reserveDataBeforeAction.symbol, - reserveDataBeforeAction.marketStableRate, - utilizationRateAfterTx, - expectedReserveData.principalStableDebt, - expectedVariableDebtAfterTx, - expectedReserveData.averageStableBorrowRate - ); - - expectedReserveData.liquidityRate = ratesAfterTx[0]; - - expectedReserveData.stableBorrowRate = ratesAfterTx[1]; - - expectedReserveData.variableBorrowRate = ratesAfterTx[2]; - - expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( - expectedReserveData.principalStableDebt, - expectedReserveData.averageStableBorrowRate, - txTimestamp, - currentTimestamp - ); - - expectedReserveData.totalVariableDebt = reserveDataBeforeAction.scaledVariableDebt.rayMul( - calcExpectedReserveNormalizedDebt( - expectedReserveData.variableBorrowRate, - expectedReserveData.variableBorrowIndex, - txTimestamp, - currentTimestamp - ) - ); - - expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity - .plus(expectedReserveData.totalVariableDebt) - .plus(expectedReserveData.totalStableDebt); - - expectedReserveData.utilizationRate = calcExpectedUtilizationRate( - expectedReserveData.totalStableDebt, - expectedReserveData.totalVariableDebt, - expectedReserveData.totalLiquidity - ); - } else { - expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt; - - const totalStableDebtAfterTx = calcExpectedStableDebtTokenBalance( - reserveDataBeforeAction.principalStableDebt, - reserveDataBeforeAction.averageStableBorrowRate, - reserveDataBeforeAction.totalStableDebtLastUpdated, - txTimestamp - ); - - expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( - reserveDataBeforeAction.principalStableDebt, - reserveDataBeforeAction.averageStableBorrowRate, - reserveDataBeforeAction.totalStableDebtLastUpdated, - currentTimestamp - ); - - expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate; - - expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.plus( - amountBorrowedBN.rayDiv(expectedReserveData.variableBorrowIndex) - ); - - const totalVariableDebtAfterTx = expectedReserveData.scaledVariableDebt.rayMul( - expectedReserveData.variableBorrowIndex - ); - - const utilizationRateAfterTx = calcExpectedUtilizationRate( - totalStableDebtAfterTx, - totalVariableDebtAfterTx, - expectedReserveData.availableLiquidity - .plus(totalStableDebtAfterTx) - .plus(totalVariableDebtAfterTx) - ); - - const rates = calcExpectedInterestRates( - reserveDataBeforeAction.symbol, - reserveDataBeforeAction.marketStableRate, - utilizationRateAfterTx, - totalStableDebtAfterTx, - totalVariableDebtAfterTx, - expectedReserveData.averageStableBorrowRate - ); - - expectedReserveData.liquidityRate = rates[0]; - - expectedReserveData.stableBorrowRate = rates[1]; - - expectedReserveData.variableBorrowRate = rates[2]; - - expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( - calcExpectedReserveNormalizedDebt( - expectedReserveData.variableBorrowRate, - expectedReserveData.variableBorrowIndex, - txTimestamp, - currentTimestamp - ) - ); - - expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity - .plus(expectedReserveData.totalStableDebt) - .plus(expectedReserveData.totalVariableDebt); - - expectedReserveData.utilizationRate = calcExpectedUtilizationRate( - expectedReserveData.totalStableDebt, - expectedReserveData.totalVariableDebt, - expectedReserveData.totalLiquidity - ); - } - - return expectedReserveData; -}; - -export const calcExpectedReserveDataAfterRepay = ( - amountRepaid: string, - borrowRateMode: RateMode, - reserveDataBeforeAction: ReserveData, - userDataBeforeAction: UserReserveData, - txTimestamp: BigNumber, - currentTimestamp: BigNumber -): ReserveData => { - const expectedReserveData: ReserveData = {}; - - expectedReserveData.address = reserveDataBeforeAction.address; - - let amountRepaidBN = new BigNumber(amountRepaid); - - const userStableDebt = calcExpectedStableDebtTokenBalance( - userDataBeforeAction.principalStableDebt, - userDataBeforeAction.stableBorrowRate, - userDataBeforeAction.stableRateLastUpdated, - txTimestamp - ); - - const userVariableDebt = calcExpectedVariableDebtTokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ); - - //if amount repaid == MAX_UINT_AMOUNT, user is repaying everything - if (amountRepaidBN.abs().eq(MAX_UINT_AMOUNT)) { - if (borrowRateMode == RateMode.Stable) { - amountRepaidBN = userStableDebt; - } else { - amountRepaidBN = userVariableDebt; - } - } - - expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( - reserveDataBeforeAction, - txTimestamp - ); - expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( - reserveDataBeforeAction, - txTimestamp - ); - - if (borrowRateMode == RateMode.Stable) { - const expectedDebt = calcExpectedTotalStableDebt( - reserveDataBeforeAction.principalStableDebt, - reserveDataBeforeAction.averageStableBorrowRate, - reserveDataBeforeAction.totalStableDebtLastUpdated, - txTimestamp - ); - - expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = expectedDebt.minus( - amountRepaidBN - ); - - //due to accumulation errors, the total stable debt might be smaller than the last user debt. - //in this case we simply set the total supply and avg stable rate to 0. - if (expectedReserveData.totalStableDebt.lt(0)) { - expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = expectedReserveData.averageStableBorrowRate = new BigNumber( - 0 - ); - } else { - expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( - reserveDataBeforeAction.averageStableBorrowRate, - expectedDebt, - amountRepaidBN.negated(), - userDataBeforeAction.stableBorrowRate - ); - - //also due to accumulation errors, the final avg stable rate when the last user repays might be negative. - //if that is the case, it means a small leftover of total stable debt is left, which can be erased. - - if (expectedReserveData.averageStableBorrowRate.lt(0)) { - expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = expectedReserveData.averageStableBorrowRate = new BigNumber( - 0 - ); - } - } - - expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; - - expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( - expectedReserveData.variableBorrowIndex - ); - } else { - expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.minus( - amountRepaidBN.rayDiv(expectedReserveData.variableBorrowIndex) - ); - - expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( - expectedReserveData.variableBorrowIndex - ); - - expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt; - expectedReserveData.totalStableDebt = reserveDataBeforeAction.totalStableDebt; - - expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate; - } - - expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity.plus( - amountRepaidBN - ); - - expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity - .plus(expectedReserveData.totalStableDebt) - .plus(expectedReserveData.totalVariableDebt); - - expectedReserveData.utilizationRate = calcExpectedUtilizationRate( - expectedReserveData.totalStableDebt, - expectedReserveData.totalVariableDebt, - expectedReserveData.totalLiquidity - ); - - const rates = calcExpectedInterestRates( - reserveDataBeforeAction.symbol, - reserveDataBeforeAction.marketStableRate, - expectedReserveData.utilizationRate, - expectedReserveData.totalStableDebt, - expectedReserveData.totalVariableDebt, - expectedReserveData.averageStableBorrowRate - ); - expectedReserveData.liquidityRate = rates[0]; - - expectedReserveData.stableBorrowRate = rates[1]; - - expectedReserveData.variableBorrowRate = rates[2]; - - expectedReserveData.lastUpdateTimestamp = txTimestamp; - - return expectedReserveData; -}; - -export const calcExpectedUserDataAfterBorrow = ( - amountBorrowed: string, - interestRateMode: string, - reserveDataBeforeAction: ReserveData, - expectedDataAfterAction: ReserveData, - userDataBeforeAction: UserReserveData, - txTimestamp: BigNumber, - currentTimestamp: BigNumber -): UserReserveData => { - const expectedUserData = {}; - - const amountBorrowedBN = new BigNumber(amountBorrowed); - - if (interestRateMode == RateMode.Stable) { - const stableDebtUntilTx = calcExpectedStableDebtTokenBalance( - userDataBeforeAction.principalStableDebt, - userDataBeforeAction.stableBorrowRate, - userDataBeforeAction.stableRateLastUpdated, - txTimestamp - ); - - expectedUserData.principalStableDebt = stableDebtUntilTx.plus(amountBorrowed); - expectedUserData.stableRateLastUpdated = txTimestamp; - - expectedUserData.stableBorrowRate = calcExpectedUserStableRate( - stableDebtUntilTx, - userDataBeforeAction.stableBorrowRate, - amountBorrowedBN, - reserveDataBeforeAction.stableBorrowRate - ); - - expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance( - expectedUserData.principalStableDebt, - expectedUserData.stableBorrowRate, - txTimestamp, - currentTimestamp - ); - - expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt; - } else { - expectedUserData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.plus( - amountBorrowedBN.rayDiv(expectedDataAfterAction.variableBorrowIndex) - ); - - expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; - - expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; - - expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated; - - expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance( - userDataBeforeAction.principalStableDebt, - userDataBeforeAction.stableBorrowRate, - userDataBeforeAction.stableRateLastUpdated, - currentTimestamp - ); - } - - expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( - expectedDataAfterAction, - expectedUserData, - currentTimestamp - ); - - expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; - - expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled; - - expectedUserData.currentATokenBalance = calcExpectedATokenBalance( - expectedDataAfterAction, - userDataBeforeAction, - currentTimestamp - ); - - expectedUserData.scaledATokenBalance = userDataBeforeAction.scaledATokenBalance; - - expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountBorrowed); - - return expectedUserData; -}; - -export const calcExpectedUserDataAfterRepay = ( - totalRepaid: string, - rateMode: RateMode, - reserveDataBeforeAction: ReserveData, - expectedDataAfterAction: ReserveData, - userDataBeforeAction: UserReserveData, - user: string, - onBehalfOf: string, - txTimestamp: BigNumber, - currentTimestamp: BigNumber -): UserReserveData => { - const expectedUserData = {}; - - const variableDebt = calcExpectedVariableDebtTokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - currentTimestamp - ); - - const stableDebt = calcExpectedStableDebtTokenBalance( - userDataBeforeAction.principalStableDebt, - userDataBeforeAction.stableBorrowRate, - userDataBeforeAction.stableRateLastUpdated, - currentTimestamp - ); - - let totalRepaidBN = new BigNumber(totalRepaid); - if (totalRepaidBN.abs().eq(MAX_UINT_AMOUNT)) { - totalRepaidBN = rateMode == RateMode.Stable ? stableDebt : variableDebt; - } - - if (rateMode == RateMode.Stable) { - expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt; - expectedUserData.currentVariableDebt = variableDebt; - - expectedUserData.principalStableDebt = expectedUserData.currentStableDebt = stableDebt.minus( - totalRepaidBN - ); - - if (expectedUserData.currentStableDebt.eq('0')) { - //user repaid everything - expectedUserData.stableBorrowRate = expectedUserData.stableRateLastUpdated = new BigNumber( - '0' - ); - } else { - expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; - expectedUserData.stableRateLastUpdated = txTimestamp; - } - } else { - expectedUserData.currentStableDebt = userDataBeforeAction.principalStableDebt; - expectedUserData.principalStableDebt = stableDebt; - expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; - expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated; - - expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt.minus( - totalRepaidBN.rayDiv(expectedDataAfterAction.variableBorrowIndex) - ); - expectedUserData.currentVariableDebt = expectedUserData.scaledVariableDebt.rayMul( - expectedDataAfterAction.variableBorrowIndex - ); - } - - expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; - - expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled; - - expectedUserData.currentATokenBalance = calcExpectedATokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ); - expectedUserData.scaledATokenBalance = userDataBeforeAction.scaledATokenBalance; - - if (user === onBehalfOf) { - expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(totalRepaidBN); - } else { - //wallet balance didn't change - expectedUserData.walletBalance = userDataBeforeAction.walletBalance; - } - - return expectedUserData; -}; - -export const calcExpectedUserDataAfterSetUseAsCollateral = ( - useAsCollateral: boolean, - reserveDataBeforeAction: ReserveData, - userDataBeforeAction: UserReserveData, - txCost: BigNumber -): UserReserveData => { - const expectedUserData = { ...userDataBeforeAction }; - - expectedUserData.usageAsCollateralEnabled = useAsCollateral; - - return expectedUserData; -}; - -export const calcExpectedReserveDataAfterSwapRateMode = ( - reserveDataBeforeAction: ReserveData, - userDataBeforeAction: UserReserveData, - rateMode: string, - txTimestamp: BigNumber -): ReserveData => { - const expectedReserveData: ReserveData = {}; - - expectedReserveData.address = reserveDataBeforeAction.address; - - const variableDebt = calcExpectedVariableDebtTokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ); - - const stableDebt = calcExpectedStableDebtTokenBalance( - userDataBeforeAction.principalStableDebt, - userDataBeforeAction.stableBorrowRate, - userDataBeforeAction.stableRateLastUpdated, - txTimestamp - ); - - expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( - reserveDataBeforeAction, - txTimestamp - ); - - expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( - reserveDataBeforeAction, - txTimestamp - ); - - expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity; - - const totalStableDebtUntilTx = calcExpectedTotalStableDebt( - reserveDataBeforeAction.principalStableDebt, - reserveDataBeforeAction.averageStableBorrowRate, - reserveDataBeforeAction.totalStableDebtLastUpdated, - txTimestamp - ); - - if (rateMode === RateMode.Stable) { - //swap user stable debt to variable - expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.plus( - stableDebt.rayDiv(expectedReserveData.variableBorrowIndex) - ); - - expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( - expectedReserveData.variableBorrowIndex - ); - - expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = totalStableDebtUntilTx.minus( - stableDebt - ); - - expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( - reserveDataBeforeAction.averageStableBorrowRate, - expectedReserveData.principalStableDebt.plus(stableDebt), - stableDebt.negated(), - userDataBeforeAction.stableBorrowRate - ); - } else { - //swap variable to stable - - expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = totalStableDebtUntilTx.plus( - variableDebt - ); - - expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.minus( - variableDebt.rayDiv(expectedReserveData.variableBorrowIndex) - ); - - expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( - expectedReserveData.variableBorrowIndex - ); - - expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate( - reserveDataBeforeAction.averageStableBorrowRate, - reserveDataBeforeAction.totalStableDebt, - variableDebt, - reserveDataBeforeAction.stableBorrowRate - ); - } - - expectedReserveData.totalLiquidity = reserveDataBeforeAction.availableLiquidity - .plus(expectedReserveData.totalStableDebt) - .plus(expectedReserveData.totalVariableDebt); - - expectedReserveData.utilizationRate = calcExpectedUtilizationRate( - expectedReserveData.totalStableDebt, - expectedReserveData.totalVariableDebt, - expectedReserveData.totalLiquidity - ); - - const rates = calcExpectedInterestRates( - reserveDataBeforeAction.symbol, - reserveDataBeforeAction.marketStableRate, - expectedReserveData.utilizationRate, - expectedReserveData.totalStableDebt, - expectedReserveData.totalVariableDebt, - expectedReserveData.averageStableBorrowRate - ); - expectedReserveData.liquidityRate = rates[0]; - - expectedReserveData.stableBorrowRate = rates[1]; - - expectedReserveData.variableBorrowRate = rates[2]; - - return expectedReserveData; -}; - -export const calcExpectedUserDataAfterSwapRateMode = ( - reserveDataBeforeAction: ReserveData, - expectedDataAfterAction: ReserveData, - userDataBeforeAction: UserReserveData, - rateMode: string, - txCost: BigNumber, - txTimestamp: BigNumber -): UserReserveData => { - const expectedUserData = { ...userDataBeforeAction }; - - const stableDebtBalance = calcExpectedStableDebtTokenBalance( - userDataBeforeAction.principalStableDebt, - userDataBeforeAction.stableBorrowRate, - userDataBeforeAction.stableRateLastUpdated, - txTimestamp - ); - - const variableDebtBalance = calcExpectedVariableDebtTokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ); - - expectedUserData.currentATokenBalance = calcExpectedATokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ); - - if (rateMode === RateMode.Stable) { - // swap to variable - expectedUserData.currentStableDebt = expectedUserData.principalStableDebt = new BigNumber(0); - - expectedUserData.stableBorrowRate = new BigNumber(0); - - expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt.plus( - stableDebtBalance.rayDiv(expectedDataAfterAction.variableBorrowIndex) - ); - expectedUserData.currentVariableDebt = expectedUserData.scaledVariableDebt.rayMul( - expectedDataAfterAction.variableBorrowIndex - ); - - expectedUserData.stableRateLastUpdated = new BigNumber(0); - } else { - expectedUserData.principalStableDebt = expectedUserData.currentStableDebt = userDataBeforeAction.currentStableDebt.plus( - variableDebtBalance - ); - - //weighted average of the previous and the current - expectedUserData.stableBorrowRate = calcExpectedUserStableRate( - stableDebtBalance, - userDataBeforeAction.stableBorrowRate, - variableDebtBalance, - reserveDataBeforeAction.stableBorrowRate - ); - - expectedUserData.stableRateLastUpdated = txTimestamp; - - expectedUserData.currentVariableDebt = expectedUserData.scaledVariableDebt = new BigNumber(0); - } - - expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; - - return expectedUserData; -}; - -export const calcExpectedReserveDataAfterStableRateRebalance = ( - reserveDataBeforeAction: ReserveData, - userDataBeforeAction: UserReserveData, - txTimestamp: BigNumber -): ReserveData => { - const expectedReserveData: ReserveData = {}; - - expectedReserveData.address = reserveDataBeforeAction.address; - - const userStableDebt = calcExpectedStableDebtTokenBalance( - userDataBeforeAction.principalStableDebt, - userDataBeforeAction.stableBorrowRate, - userDataBeforeAction.stableRateLastUpdated, - txTimestamp - ); - - expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex( - reserveDataBeforeAction, - txTimestamp - ); - - expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex( - reserveDataBeforeAction, - txTimestamp - ); - - expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt; - expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul( - expectedReserveData.variableBorrowIndex - ); - - expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt( - reserveDataBeforeAction.principalStableDebt, - reserveDataBeforeAction.averageStableBorrowRate, - reserveDataBeforeAction.totalStableDebtLastUpdated, - txTimestamp - ); - - expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity; - - expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity - .plus(expectedReserveData.totalStableDebt) - .plus(expectedReserveData.totalVariableDebt); - - //removing the stable liquidity at the old rate - - const avgRateBefore = calcExpectedAverageStableBorrowRateRebalance( - reserveDataBeforeAction.averageStableBorrowRate, - expectedReserveData.totalStableDebt, - userStableDebt.negated(), - userDataBeforeAction.stableBorrowRate - ); - // adding it again at the new rate - - expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRateRebalance( - avgRateBefore, - expectedReserveData.totalStableDebt.minus(userStableDebt), - userStableDebt, - reserveDataBeforeAction.stableBorrowRate - ); - - expectedReserveData.utilizationRate = calcExpectedUtilizationRate( - expectedReserveData.totalStableDebt, - expectedReserveData.totalVariableDebt, - expectedReserveData.totalLiquidity - ); - - const rates = calcExpectedInterestRates( - reserveDataBeforeAction.symbol, - reserveDataBeforeAction.marketStableRate, - expectedReserveData.utilizationRate, - expectedReserveData.totalStableDebt, - expectedReserveData.totalVariableDebt, - expectedReserveData.averageStableBorrowRate - ); - - expectedReserveData.liquidityRate = rates[0]; - - expectedReserveData.stableBorrowRate = rates[1]; - - expectedReserveData.variableBorrowRate = rates[2]; - - return expectedReserveData; -}; - -export const calcExpectedUserDataAfterStableRateRebalance = ( - reserveDataBeforeAction: ReserveData, - expectedDataAfterAction: ReserveData, - userDataBeforeAction: UserReserveData, - txCost: BigNumber, - txTimestamp: BigNumber -): UserReserveData => { - const expectedUserData = { ...userDataBeforeAction }; - - expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt; - - expectedUserData.principalVariableDebt = calcExpectedVariableDebtTokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ); - expectedUserData.currentStableDebt = expectedUserData.principalStableDebt = calcExpectedStableDebtTokenBalance( - userDataBeforeAction.principalStableDebt, - userDataBeforeAction.stableBorrowRate, - userDataBeforeAction.stableRateLastUpdated, - txTimestamp - ); - - expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ); - - expectedUserData.stableRateLastUpdated = txTimestamp; - - expectedUserData.principalVariableDebt = userDataBeforeAction.principalVariableDebt; - - // Stable rate after burn - expectedUserData.stableBorrowRate = expectedDataAfterAction.averageStableBorrowRate; - expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; - - expectedUserData.currentATokenBalance = calcExpectedATokenBalance( - reserveDataBeforeAction, - userDataBeforeAction, - txTimestamp - ); - - return expectedUserData; -}; - -const calcExpectedScaledATokenBalance = ( - userDataBeforeAction: UserReserveData, - index: BigNumber, - amountAdded: BigNumber, - amountTaken: BigNumber -) => { - return userDataBeforeAction.scaledATokenBalance - .plus(amountAdded.rayDiv(index)) - .minus(amountTaken.rayDiv(index)); -}; - -export const calcExpectedATokenBalance = ( - reserveData: ReserveData, - userData: UserReserveData, - currentTimestamp: BigNumber -) => { - const index = calcExpectedReserveNormalizedIncome(reserveData, currentTimestamp); - - const { scaledATokenBalance: scaledBalanceBeforeAction } = userData; - - return scaledBalanceBeforeAction.rayMul(index); -}; - -const calcExpectedAverageStableBorrowRate = ( - avgStableRateBefore: BigNumber, - totalStableDebtBefore: BigNumber, - amountChanged: string | BigNumber, - rate: BigNumber -) => { - const weightedTotalBorrows = avgStableRateBefore.multipliedBy(totalStableDebtBefore); - const weightedAmountBorrowed = rate.multipliedBy(amountChanged); - const totalBorrowedStable = totalStableDebtBefore.plus(amountChanged); - - if (totalBorrowedStable.eq(0)) return new BigNumber('0'); - - return weightedTotalBorrows - .plus(weightedAmountBorrowed) - .div(totalBorrowedStable) - .decimalPlaces(0, BigNumber.ROUND_DOWN); -}; - -const calcExpectedAverageStableBorrowRateRebalance = ( - avgStableRateBefore: BigNumber, - totalStableDebtBefore: BigNumber, - amountChanged: BigNumber, - rate: BigNumber -) => { - const weightedTotalBorrows = avgStableRateBefore.rayMul(totalStableDebtBefore); - const weightedAmountBorrowed = rate.rayMul(amountChanged.wadToRay()); - const totalBorrowedStable = totalStableDebtBefore.plus(amountChanged.wadToRay()); - - if (totalBorrowedStable.eq(0)) return new BigNumber('0'); - - return weightedTotalBorrows - .plus(weightedAmountBorrowed) - .rayDiv(totalBorrowedStable) - .decimalPlaces(0, BigNumber.ROUND_DOWN); -}; - -export const calcExpectedVariableDebtTokenBalance = ( - reserveData: ReserveData, - userData: UserReserveData, - currentTimestamp: BigNumber -) => { - const normalizedDebt = calcExpectedReserveNormalizedDebt( - reserveData.variableBorrowRate, - reserveData.variableBorrowIndex, - reserveData.lastUpdateTimestamp, - currentTimestamp - ); - - const { scaledVariableDebt } = userData; - - return scaledVariableDebt.rayMul(normalizedDebt); -}; - -export const calcExpectedStableDebtTokenBalance = ( - principalStableDebt: BigNumber, - stableBorrowRate: BigNumber, - stableRateLastUpdated: BigNumber, - currentTimestamp: BigNumber -) => { - if ( - stableBorrowRate.eq(0) || - currentTimestamp.eq(stableRateLastUpdated) || - stableRateLastUpdated.eq(0) - ) { - return principalStableDebt; - } - - const cumulatedInterest = calcCompoundedInterest( - stableBorrowRate, - currentTimestamp, - stableRateLastUpdated - ); - - return principalStableDebt.rayMul(cumulatedInterest); -}; - -const calcLinearInterest = ( - rate: BigNumber, - currentTimestamp: BigNumber, - lastUpdateTimestamp: BigNumber -) => { - const timeDifference = currentTimestamp.minus(lastUpdateTimestamp); - - const cumulatedInterest = rate - .multipliedBy(timeDifference) - .dividedBy(new BigNumber(ONE_YEAR)) - .plus(RAY); - - return cumulatedInterest; -}; - -const calcCompoundedInterest = ( - rate: BigNumber, - currentTimestamp: BigNumber, - lastUpdateTimestamp: BigNumber -) => { - const timeDifference = currentTimestamp.minus(lastUpdateTimestamp); - - if (timeDifference.eq(0)) { - return new BigNumber(RAY); - } - - const expMinusOne = timeDifference.minus(1); - const expMinusTwo = timeDifference.gt(2) ? timeDifference.minus(2) : 0; - - const ratePerSecond = rate.div(ONE_YEAR); - - const basePowerTwo = ratePerSecond.rayMul(ratePerSecond); - const basePowerThree = basePowerTwo.rayMul(ratePerSecond); - - const secondTerm = timeDifference.times(expMinusOne).times(basePowerTwo).div(2); - const thirdTerm = timeDifference - .times(expMinusOne) - .times(expMinusTwo) - .times(basePowerThree) - .div(6); - - return new BigNumber(RAY) - .plus(ratePerSecond.times(timeDifference)) - .plus(secondTerm) - .plus(thirdTerm); -}; - -export const calcExpectedInterestRates = ( - reserveSymbol: string, - marketStableRate: BigNumber, - utilizationRate: BigNumber, - totalStableDebt: BigNumber, - totalVariableDebt: BigNumber, - averageStableBorrowRate: BigNumber -): BigNumber[] => { - const { reservesParams } = configuration; - - const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol); - const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[ - reserveIndex - ]; - - let stableBorrowRate: BigNumber = marketStableRate; - let variableBorrowRate: BigNumber = new BigNumber(reserveConfiguration.strategy.baseVariableBorrowRate); - - const optimalRate = new BigNumber(reserveConfiguration.strategy.optimalUtilizationRate); - const excessRate = new BigNumber(RAY).minus(optimalRate); - if (utilizationRate.gt(optimalRate)) { - const excessUtilizationRateRatio = utilizationRate - .minus(reserveConfiguration.strategy.optimalUtilizationRate) - .rayDiv(excessRate); - - stableBorrowRate = stableBorrowRate - .plus(reserveConfiguration.strategy.stableRateSlope1) - .plus( - new BigNumber(reserveConfiguration.strategy.stableRateSlope2).rayMul(excessUtilizationRateRatio) - ); - - variableBorrowRate = variableBorrowRate - .plus(reserveConfiguration.strategy.variableRateSlope1) - .plus( - new BigNumber(reserveConfiguration.strategy.variableRateSlope2).rayMul(excessUtilizationRateRatio) - ); - } else { - stableBorrowRate = stableBorrowRate.plus( - new BigNumber(reserveConfiguration.strategy.stableRateSlope1).rayMul( - utilizationRate.rayDiv(new BigNumber(optimalRate)) - ) - ); - - variableBorrowRate = variableBorrowRate.plus( - utilizationRate - .rayDiv(optimalRate) - .rayMul(new BigNumber(reserveConfiguration.strategy.variableRateSlope1)) - ); - } - - const expectedOverallRate = calcExpectedOverallBorrowRate( - totalStableDebt, - totalVariableDebt, - variableBorrowRate, - averageStableBorrowRate - ); - const liquidityRate = expectedOverallRate - .rayMul(utilizationRate) - .percentMul(new BigNumber(PERCENTAGE_FACTOR).minus(reserveConfiguration.reserveFactor)); - - return [liquidityRate, stableBorrowRate, variableBorrowRate]; -}; - -export const calcExpectedOverallBorrowRate = ( - totalStableDebt: BigNumber, - totalVariableDebt: BigNumber, - currentVariableBorrowRate: BigNumber, - currentAverageStableBorrowRate: BigNumber -): BigNumber => { - const totalBorrows = totalStableDebt.plus(totalVariableDebt); - - if (totalBorrows.eq(0)) return strToBN('0'); - - const weightedVariableRate = totalVariableDebt.wadToRay().rayMul(currentVariableBorrowRate); - - const weightedStableRate = totalStableDebt.wadToRay().rayMul(currentAverageStableBorrowRate); - - const overallBorrowRate = weightedVariableRate - .plus(weightedStableRate) - .rayDiv(totalBorrows.wadToRay()); - - return overallBorrowRate; -}; - -export const calcExpectedUtilizationRate = ( - totalStableDebt: BigNumber, - totalVariableDebt: BigNumber, - totalLiquidity: BigNumber -): BigNumber => { - if (totalStableDebt.eq('0') && totalVariableDebt.eq('0')) { - return strToBN('0'); - } - - const utilization = totalStableDebt.plus(totalVariableDebt).rayDiv(totalLiquidity); - - return utilization; -}; - -const calcExpectedReserveNormalizedIncome = ( - reserveData: ReserveData, - currentTimestamp: BigNumber -) => { - const { liquidityRate, liquidityIndex, lastUpdateTimestamp } = reserveData; - - //if utilization rate is 0, nothing to compound - if (liquidityRate.eq('0')) { - return liquidityIndex; - } - - const cumulatedInterest = calcLinearInterest( - liquidityRate, - currentTimestamp, - lastUpdateTimestamp - ); - - const income = cumulatedInterest.rayMul(liquidityIndex); - - return income; -}; - -const calcExpectedReserveNormalizedDebt = ( - variableBorrowRate: BigNumber, - variableBorrowIndex: BigNumber, - lastUpdateTimestamp: BigNumber, - currentTimestamp: BigNumber -) => { - //if utilization rate is 0, nothing to compound - if (variableBorrowRate.eq('0')) { - return variableBorrowIndex; - } - - const cumulatedInterest = calcCompoundedInterest( - variableBorrowRate, - currentTimestamp, - lastUpdateTimestamp - ); - - const debt = cumulatedInterest.rayMul(variableBorrowIndex); - - return debt; -}; - -const calcExpectedUserStableRate = ( - balanceBefore: BigNumber, - rateBefore: BigNumber, - amount: BigNumber, - rateNew: BigNumber -) => { - return balanceBefore - .times(rateBefore) - .plus(amount.times(rateNew)) - .div(balanceBefore.plus(amount)); -}; - -const calcExpectedLiquidityIndex = (reserveData: ReserveData, timestamp: BigNumber) => { - //if utilization rate is 0, nothing to compound - if (reserveData.utilizationRate.eq('0')) { - return reserveData.liquidityIndex; - } - - const cumulatedInterest = calcLinearInterest( - reserveData.liquidityRate, - timestamp, - reserveData.lastUpdateTimestamp - ); - - return cumulatedInterest.rayMul(reserveData.liquidityIndex); -}; - -const calcExpectedVariableBorrowIndex = (reserveData: ReserveData, timestamp: BigNumber) => { - //if totalVariableDebt is 0, nothing to compound - if (reserveData.totalVariableDebt.eq('0')) { - return reserveData.variableBorrowIndex; - } - - const cumulatedInterest = calcCompoundedInterest( - reserveData.variableBorrowRate, - timestamp, - reserveData.lastUpdateTimestamp - ); - - return cumulatedInterest.rayMul(reserveData.variableBorrowIndex); -}; - -const calcExpectedTotalStableDebt = ( - principalStableDebt: BigNumber, - averageStableBorrowRate: BigNumber, - lastUpdateTimestamp: BigNumber, - currentTimestamp: BigNumber -) => { - const cumulatedInterest = calcCompoundedInterest( - averageStableBorrowRate, - currentTimestamp, - lastUpdateTimestamp - ); - - return cumulatedInterest.rayMul(principalStableDebt); -}; - -const calcExpectedTotalVariableDebt = ( - reserveData: ReserveData, - expectedVariableDebtIndex: BigNumber -) => { - return reserveData.scaledVariableDebt.rayMul(expectedVariableDebtIndex); -}; diff --git a/test/helpers/utils/helpers.ts b/test/helpers/utils/helpers.ts deleted file mode 100644 index fc7a9709..00000000 --- a/test/helpers/utils/helpers.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { LendingPool } from '../../../types/LendingPool'; -import { ReserveData, UserReserveData } from './interfaces'; -import { - getLendingRateOracle, - getIErc20Detailed, - getMintableERC20, - getAToken, - getStableDebtToken, - getVariableDebtToken, -} from '../../../helpers/contracts-getters'; -import { tEthereumAddress } from '../../../helpers/types'; -import BigNumber from 'bignumber.js'; -import { getDb, DRE } from '../../../helpers/misc-utils'; -import { AaveProtocolDataProvider } from '../../../types/AaveProtocolDataProvider'; - -export const getReserveData = async ( - helper: AaveProtocolDataProvider, - reserve: tEthereumAddress -): Promise => { - const [reserveData, tokenAddresses, rateOracle, token] = await Promise.all([ - helper.getReserveData(reserve), - helper.getReserveTokensAddresses(reserve), - getLendingRateOracle(), - getIErc20Detailed(reserve), - ]); - - const stableDebtToken = await getStableDebtToken(tokenAddresses.stableDebtTokenAddress); - const variableDebtToken = await getVariableDebtToken(tokenAddresses.variableDebtTokenAddress); - - const { 0: principalStableDebt } = await stableDebtToken.getSupplyData(); - const totalStableDebtLastUpdated = await stableDebtToken.getTotalSupplyLastUpdated(); - - const scaledVariableDebt = await variableDebtToken.scaledTotalSupply(); - - const rate = (await rateOracle.getMarketBorrowRate(reserve)).toString(); - const symbol = await token.symbol(); - const decimals = new BigNumber(await token.decimals()); - - const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) - .plus(reserveData.totalStableDebt.toString()) - .plus(reserveData.totalVariableDebt.toString()); - - const utilizationRate = new BigNumber( - totalLiquidity.eq(0) - ? 0 - : new BigNumber(reserveData.totalStableDebt.toString()) - .plus(reserveData.totalVariableDebt.toString()) - .rayDiv(totalLiquidity) - ); - - return { - totalLiquidity, - utilizationRate, - availableLiquidity: new BigNumber(reserveData.availableLiquidity.toString()), - totalStableDebt: new BigNumber(reserveData.totalStableDebt.toString()), - totalVariableDebt: new BigNumber(reserveData.totalVariableDebt.toString()), - liquidityRate: new BigNumber(reserveData.liquidityRate.toString()), - variableBorrowRate: new BigNumber(reserveData.variableBorrowRate.toString()), - stableBorrowRate: new BigNumber(reserveData.stableBorrowRate.toString()), - averageStableBorrowRate: new BigNumber(reserveData.averageStableBorrowRate.toString()), - liquidityIndex: new BigNumber(reserveData.liquidityIndex.toString()), - variableBorrowIndex: new BigNumber(reserveData.variableBorrowIndex.toString()), - lastUpdateTimestamp: new BigNumber(reserveData.lastUpdateTimestamp), - totalStableDebtLastUpdated: new BigNumber(totalStableDebtLastUpdated), - principalStableDebt: new BigNumber(principalStableDebt.toString()), - scaledVariableDebt: new BigNumber(scaledVariableDebt.toString()), - address: reserve, - aTokenAddress: tokenAddresses.aTokenAddress, - symbol, - decimals, - marketStableRate: new BigNumber(rate), - }; -}; - -export const getUserData = async ( - pool: LendingPool, - helper: AaveProtocolDataProvider, - reserve: string, - user: tEthereumAddress, - sender?: tEthereumAddress -): Promise => { - const [userData, scaledATokenBalance] = await Promise.all([ - helper.getUserReserveData(reserve, user), - getATokenUserData(reserve, user, helper), - ]); - - const token = await getMintableERC20(reserve); - const walletBalance = new BigNumber((await token.balanceOf(sender || user)).toString()); - - return { - scaledATokenBalance: new BigNumber(scaledATokenBalance), - currentATokenBalance: new BigNumber(userData.currentATokenBalance.toString()), - currentStableDebt: new BigNumber(userData.currentStableDebt.toString()), - currentVariableDebt: new BigNumber(userData.currentVariableDebt.toString()), - principalStableDebt: new BigNumber(userData.principalStableDebt.toString()), - scaledVariableDebt: new BigNumber(userData.scaledVariableDebt.toString()), - stableBorrowRate: new BigNumber(userData.stableBorrowRate.toString()), - liquidityRate: new BigNumber(userData.liquidityRate.toString()), - usageAsCollateralEnabled: userData.usageAsCollateralEnabled, - stableRateLastUpdated: new BigNumber(userData.stableRateLastUpdated.toString()), - walletBalance, - }; -}; - -export const getReserveAddressFromSymbol = async (symbol: string) => { - const token = await getMintableERC20( - (await getDb().get(`${symbol}.${DRE.network.name}`).value()).address - ); - - if (!token) { - throw `Could not find instance for contract ${symbol}`; - } - return token.address; -}; - -const getATokenUserData = async ( - reserve: string, - user: string, - helpersContract: AaveProtocolDataProvider -) => { - const aTokenAddress: string = (await helpersContract.getReserveTokensAddresses(reserve)) - .aTokenAddress; - - const aToken = await getAToken(aTokenAddress); - - const scaledBalance = await aToken.scaledBalanceOf(user); - return scaledBalance.toString(); -}; diff --git a/test/helpers/utils/interfaces/index.ts b/test/helpers/utils/interfaces/index.ts deleted file mode 100644 index 17660fcc..00000000 --- a/test/helpers/utils/interfaces/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -import BigNumber from 'bignumber.js'; - -export interface UserReserveData { - scaledATokenBalance: BigNumber; - currentATokenBalance: BigNumber; - currentStableDebt: BigNumber; - currentVariableDebt: BigNumber; - principalStableDebt: BigNumber; - scaledVariableDebt: BigNumber; - liquidityRate: BigNumber; - stableBorrowRate: BigNumber; - stableRateLastUpdated: BigNumber; - usageAsCollateralEnabled: Boolean; - walletBalance: BigNumber; - [key: string]: BigNumber | string | Boolean; -} - -export interface ReserveData { - address: string; - symbol: string; - decimals: BigNumber; - totalLiquidity: BigNumber; - availableLiquidity: BigNumber; - totalStableDebt: BigNumber; - totalVariableDebt: BigNumber; - principalStableDebt: BigNumber; - scaledVariableDebt: BigNumber; - averageStableBorrowRate: BigNumber; - variableBorrowRate: BigNumber; - stableBorrowRate: BigNumber; - utilizationRate: BigNumber; - liquidityIndex: BigNumber; - variableBorrowIndex: BigNumber; - aTokenAddress: string; - marketStableRate: BigNumber; - lastUpdateTimestamp: BigNumber; - totalStableDebtLastUpdated: BigNumber; - liquidityRate: BigNumber; - [key: string]: BigNumber | string; -} diff --git a/test/helpers/utils/math.ts b/test/helpers/utils/math.ts deleted file mode 100644 index efd296e0..00000000 --- a/test/helpers/utils/math.ts +++ /dev/null @@ -1,97 +0,0 @@ -import BigNumber from 'bignumber.js'; -import { - RAY, - WAD, - HALF_RAY, - HALF_WAD, - WAD_RAY_RATIO, - HALF_PERCENTAGE, - PERCENTAGE_FACTOR, -} from '../../../helpers/constants'; - -declare module 'bignumber.js' { - interface BigNumber { - ray: () => BigNumber; - wad: () => BigNumber; - halfRay: () => BigNumber; - halfWad: () => BigNumber; - halfPercentage: () => BigNumber; - wadMul: (a: BigNumber) => BigNumber; - wadDiv: (a: BigNumber) => BigNumber; - rayMul: (a: BigNumber) => BigNumber; - rayDiv: (a: BigNumber) => BigNumber; - percentMul: (a: BigNumber) => BigNumber; - percentDiv: (a: BigNumber) => BigNumber; - rayToWad: () => BigNumber; - wadToRay: () => BigNumber; - } -} - -BigNumber.prototype.ray = (): BigNumber => { - return new BigNumber(RAY).decimalPlaces(0); -}; -BigNumber.prototype.wad = (): BigNumber => { - return new BigNumber(WAD).decimalPlaces(0); -}; - -BigNumber.prototype.halfRay = (): BigNumber => { - return new BigNumber(HALF_RAY).decimalPlaces(0, BigNumber.ROUND_DOWN); -}; - -BigNumber.prototype.halfWad = (): BigNumber => { - return new BigNumber(HALF_WAD).decimalPlaces(0, BigNumber.ROUND_DOWN); -}; - -BigNumber.prototype.wadMul = function (b: BigNumber): BigNumber { - return this.halfWad().plus(this.multipliedBy(b)).div(WAD).decimalPlaces(0, BigNumber.ROUND_DOWN); -}; - -BigNumber.prototype.wadDiv = function (a: BigNumber): BigNumber { - const halfA = a.div(2).decimalPlaces(0, BigNumber.ROUND_DOWN); - - return halfA.plus(this.multipliedBy(WAD)).div(a).decimalPlaces(0, BigNumber.ROUND_DOWN); -}; - -BigNumber.prototype.rayMul = function (a: BigNumber): BigNumber { - return this.halfRay().plus(this.multipliedBy(a)).div(RAY).decimalPlaces(0, BigNumber.ROUND_DOWN); -}; - -BigNumber.prototype.rayDiv = function (a: BigNumber): BigNumber { - const halfA = a.div(2).decimalPlaces(0, BigNumber.ROUND_DOWN); - - return halfA - .plus(this.multipliedBy(RAY)) - .decimalPlaces(0, BigNumber.ROUND_DOWN) - .div(a) - .decimalPlaces(0, BigNumber.ROUND_DOWN); -}; - -BigNumber.prototype.rayToWad = function (): BigNumber { - const halfRatio = new BigNumber(WAD_RAY_RATIO).div(2); - - return halfRatio.plus(this).div(WAD_RAY_RATIO).decimalPlaces(0, BigNumber.ROUND_DOWN); -}; - -BigNumber.prototype.wadToRay = function (): BigNumber { - return this.multipliedBy(WAD_RAY_RATIO).decimalPlaces(0, BigNumber.ROUND_DOWN); -}; - -BigNumber.prototype.halfPercentage = (): BigNumber => { - return new BigNumber(HALF_PERCENTAGE).decimalPlaces(0, BigNumber.ROUND_DOWN); -}; - -BigNumber.prototype.percentMul = function (b: BigNumber): BigNumber { - return this.halfPercentage() - .plus(this.multipliedBy(b)) - .div(PERCENTAGE_FACTOR) - .decimalPlaces(0, BigNumber.ROUND_DOWN); -}; - -BigNumber.prototype.percentDiv = function (a: BigNumber): BigNumber { - const halfA = a.div(2).decimalPlaces(0, BigNumber.ROUND_DOWN); - - return halfA - .plus(this.multipliedBy(PERCENTAGE_FACTOR)) - .div(a) - .decimalPlaces(0, BigNumber.ROUND_DOWN); -}; diff --git a/test/lending-pool-addresses-provider.spec.ts b/test/lending-pool-addresses-provider.spec.ts deleted file mode 100644 index 48570458..00000000 --- a/test/lending-pool-addresses-provider.spec.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { expect } from 'chai'; -import { createRandomAddress } from '../helpers/misc-utils'; -import { makeSuite, TestEnv } from './helpers/make-suite'; -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-deployments'; - -const { utils } = ethers; - -makeSuite('LendingPoolAddressesProvider', (testEnv: TestEnv) => { - it('Test the accessibility of the LendingPoolAddressesProvider', async () => { - const { addressesProvider, users } = testEnv; - const mockAddress = createRandomAddress(); - const { INVALID_OWNER_REVERT_MSG } = ProtocolErrors; - - await addressesProvider.transferOwnership(users[1].address); - - for (const contractFunction of [ - addressesProvider.setMarketId, - addressesProvider.setLendingPoolImpl, - addressesProvider.setLendingPoolConfiguratorImpl, - addressesProvider.setLendingPoolCollateralManager, - addressesProvider.setPoolAdmin, - addressesProvider.setPriceOracle, - addressesProvider.setLendingRateOracle, - ]) { - await expect(contractFunction(mockAddress)).to.be.revertedWith(INVALID_OWNER_REVERT_MSG); - } - - await expect( - addressesProvider.setAddress(utils.keccak256(utils.toUtf8Bytes('RANDOM_ID')), mockAddress) - ).to.be.revertedWith(INVALID_OWNER_REVERT_MSG); - - await expect( - addressesProvider.setAddressAsProxy( - utils.keccak256(utils.toUtf8Bytes('RANDOM_ID')), - mockAddress - ) - ).to.be.revertedWith(INVALID_OWNER_REVERT_MSG); - }); - - it('Tests adding a proxied address with `setAddressAsProxy()`', async () => { - const { addressesProvider, users } = testEnv; - const { INVALID_OWNER_REVERT_MSG } = ProtocolErrors; - - const currentAddressesProviderOwner = users[1]; - - const mockLendingPool = await deployLendingPool(); - const proxiedAddressId = utils.keccak256(utils.toUtf8Bytes('RANDOM_PROXIED')); - - const proxiedAddressSetReceipt = await waitForTx( - await addressesProvider - .connect(currentAddressesProviderOwner.signer) - .setAddressAsProxy(proxiedAddressId, mockLendingPool.address) - ); - - if (!proxiedAddressSetReceipt.events || proxiedAddressSetReceipt.events?.length < 1) { - throw new Error('INVALID_EVENT_EMMITED'); - } - - expect(proxiedAddressSetReceipt.events[0].event).to.be.equal('ProxyCreated'); - expect(proxiedAddressSetReceipt.events[1].event).to.be.equal('AddressSet'); - expect(proxiedAddressSetReceipt.events[1].args?.id).to.be.equal(proxiedAddressId); - expect(proxiedAddressSetReceipt.events[1].args?.newAddress).to.be.equal( - mockLendingPool.address - ); - expect(proxiedAddressSetReceipt.events[1].args?.hasProxy).to.be.equal(true); - }); - - it('Tests adding a non proxied address with `setAddress()`', async () => { - const { addressesProvider, users } = testEnv; - const { INVALID_OWNER_REVERT_MSG } = ProtocolErrors; - - const currentAddressesProviderOwner = users[1]; - const mockNonProxiedAddress = createRandomAddress(); - const nonProxiedAddressId = utils.keccak256(utils.toUtf8Bytes('RANDOM_NON_PROXIED')); - - const nonProxiedAddressSetReceipt = await waitForTx( - await addressesProvider - .connect(currentAddressesProviderOwner.signer) - .setAddress(nonProxiedAddressId, mockNonProxiedAddress) - ); - - expect(mockNonProxiedAddress.toLowerCase()).to.be.equal( - (await addressesProvider.getAddress(nonProxiedAddressId)).toLowerCase() - ); - - if (!nonProxiedAddressSetReceipt.events || nonProxiedAddressSetReceipt.events?.length < 1) { - throw new Error('INVALID_EVENT_EMMITED'); - } - - expect(nonProxiedAddressSetReceipt.events[0].event).to.be.equal('AddressSet'); - expect(nonProxiedAddressSetReceipt.events[0].args?.id).to.be.equal(nonProxiedAddressId); - expect(nonProxiedAddressSetReceipt.events[0].args?.newAddress).to.be.equal( - mockNonProxiedAddress - ); - expect(nonProxiedAddressSetReceipt.events[0].args?.hasProxy).to.be.equal(false); - }); -}); diff --git a/test/liquidation-atoken.spec.ts b/test/liquidation-atoken.spec.ts deleted file mode 100644 index 6483162c..00000000 --- a/test/liquidation-atoken.spec.ts +++ /dev/null @@ -1,379 +0,0 @@ -import BigNumber from 'bignumber.js'; - -import { DRE } from '../helpers/misc-utils'; -import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../helpers/constants'; -import { convertToCurrencyDecimals } from '../helpers/contracts-helpers'; -import { makeSuite } from './helpers/make-suite'; -import { ProtocolErrors, RateMode } from '../helpers/types'; -import { calcExpectedVariableDebtTokenBalance } from './helpers/utils/calculations'; -import { getUserData, getReserveData } from './helpers/utils/helpers'; - -const chai = require('chai'); -const { expect } = chai; - -makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) => { - const { - LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD, - INVALID_HF, - LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER, - LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED, - LP_IS_PAUSED, - } = ProtocolErrors; - - it('Deposits WETH, borrows DAI/Check liquidation fails because health factor is above 1', async () => { - const { dai, weth, users, pool, oracle } = testEnv; - const depositor = users[0]; - const borrower = users[1]; - - //mints DAI to depositor - await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); - - //approve protocol to access depositor wallet - await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - //user 1 deposits 1000 DAI - const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - await pool - .connect(depositor.signer) - .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); - - const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); - - //mints WETH to borrower - await weth.connect(borrower.signer).mint(amountETHtoDeposit); - - //approve protocol to access borrower wallet - await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - //user 2 deposits 1 WETH - await pool - .connect(borrower.signer) - .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); - - //user 2 borrows - const userGlobalData = await pool.getUserAccountData(borrower.address); - const daiPrice = await oracle.getAssetPrice(dai.address); - - const amountDAIToBorrow = await convertToCurrencyDecimals( - dai.address, - new BigNumber(userGlobalData.availableBorrowsETH.toString()) - .div(daiPrice.toString()) - .multipliedBy(0.95) - .toFixed(0) - ); - - await pool - .connect(borrower.signer) - .borrow(dai.address, amountDAIToBorrow, RateMode.Variable, '0', borrower.address); - - const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); - - expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.bignumber.equal( - '8250', - 'Invalid liquidation threshold' - ); - - //someone tries to liquidate user 2 - await expect( - pool.liquidationCall(weth.address, dai.address, borrower.address, 1, true) - ).to.be.revertedWith(LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD); - }); - - it('Drop the health factor below 1', async () => { - const { dai, users, pool, oracle } = testEnv; - const borrower = users[1]; - - const daiPrice = await oracle.getAssetPrice(dai.address); - - await oracle.setAssetPrice( - dai.address, - new BigNumber(daiPrice.toString()).multipliedBy(1.15).toFixed(0) - ); - - const userGlobalData = await pool.getUserAccountData(borrower.address); - - expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( - oneEther.toString(), - INVALID_HF - ); - }); - - it('Tries to liquidate a different currency than the loan principal', async () => { - const { pool, users, weth } = testEnv; - const borrower = users[1]; - //user 2 tries to borrow - await expect( - pool.liquidationCall(weth.address, weth.address, borrower.address, oneEther.toString(), true) - ).revertedWith(LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER); - }); - - it('Tries to liquidate a different collateral than the borrower collateral', async () => { - const { pool, dai, users } = testEnv; - const borrower = users[1]; - - await expect( - pool.liquidationCall(dai.address, dai.address, borrower.address, oneEther.toString(), true) - ).revertedWith(LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED); - }); - - it('Liquidates the borrow', async () => { - const { pool, dai, weth, aWETH, aDai, users, oracle, helpersContract, deployer } = testEnv; - const borrower = users[1]; - - //mints dai to the caller - - await dai.mint(await convertToCurrencyDecimals(dai.address, '1000')); - - //approve protocol to access depositor wallet - await dai.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const daiReserveDataBefore = await getReserveData(helpersContract, dai.address); - const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); - - const userReserveDataBefore = await getUserData( - pool, - helpersContract, - dai.address, - borrower.address - ); - - const amountToLiquidate = new BigNumber(userReserveDataBefore.currentVariableDebt.toString()) - .div(2) - .toFixed(0); - - const tx = await pool.liquidationCall( - weth.address, - dai.address, - borrower.address, - amountToLiquidate, - true - ); - - const userReserveDataAfter = await helpersContract.getUserReserveData( - dai.address, - borrower.address - ); - - const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); - - const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); - const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); - - const collateralPrice = (await oracle.getAssetPrice(weth.address)).toString(); - const principalPrice = (await oracle.getAssetPrice(dai.address)).toString(); - - const collateralDecimals = ( - await helpersContract.getReserveConfigurationData(weth.address) - ).decimals.toString(); - const principalDecimals = ( - await helpersContract.getReserveConfigurationData(dai.address) - ).decimals.toString(); - - const expectedCollateralLiquidated = new BigNumber(principalPrice) - .times(new BigNumber(amountToLiquidate).times(105)) - .times(new BigNumber(10).pow(collateralDecimals)) - .div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals))) - .decimalPlaces(0, BigNumber.ROUND_DOWN); - - if (!tx.blockNumber) { - expect(false, 'Invalid block number'); - return; - } - - const txTimestamp = new BigNumber( - (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp - ); - - const variableDebtBeforeTx = calcExpectedVariableDebtTokenBalance( - daiReserveDataBefore, - userReserveDataBefore, - txTimestamp - ); - - expect(userGlobalDataAfter.healthFactor.toString()).to.be.bignumber.gt( - oneEther.toFixed(0), - 'Invalid health factor' - ); - - expect(userReserveDataAfter.currentVariableDebt.toString()).to.be.bignumber.almostEqual( - new BigNumber(variableDebtBeforeTx).minus(amountToLiquidate).toFixed(0), - 'Invalid user borrow balance after liquidation' - ); - - expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(daiReserveDataBefore.availableLiquidity.toString()) - .plus(amountToLiquidate) - .toFixed(0), - 'Invalid principal available liquidity' - ); - - //the liquidity index of the principal reserve needs to be bigger than the index before - expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( - daiReserveDataBefore.liquidityIndex.toString(), - 'Invalid liquidity index' - ); - - //the principal APY after a liquidation needs to be lower than the APY before - expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( - daiReserveDataBefore.liquidityRate.toString(), - 'Invalid liquidity APY' - ); - - expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(ethReserveDataBefore.availableLiquidity.toString()).toFixed(0), - 'Invalid collateral available liquidity' - ); - - expect( - (await helpersContract.getUserReserveData(weth.address, deployer.address)) - .usageAsCollateralEnabled - ).to.be.true; - }); - - it('User 3 deposits 1000 USDC, user 4 1 WETH, user 4 borrows - drops HF, liquidates the borrow', async () => { - const { users, pool, usdc, oracle, weth, helpersContract } = testEnv; - const depositor = users[3]; - const borrower = users[4]; - - //mints USDC to depositor - await usdc - .connect(depositor.signer) - .mint(await convertToCurrencyDecimals(usdc.address, '1000')); - - //approve protocol to access depositor wallet - await usdc.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - //user 3 deposits 1000 USDC - const amountUSDCtoDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); - - await pool - .connect(depositor.signer) - .deposit(usdc.address, amountUSDCtoDeposit, depositor.address, '0'); - - //user 4 deposits 1 ETH - const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); - - //mints WETH to borrower - await weth.connect(borrower.signer).mint(amountETHtoDeposit); - - //approve protocol to access borrower wallet - await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - await pool - .connect(borrower.signer) - .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); - - //user 4 borrows - const userGlobalData = await pool.getUserAccountData(borrower.address); - - const usdcPrice = await oracle.getAssetPrice(usdc.address); - - const amountUSDCToBorrow = await convertToCurrencyDecimals( - usdc.address, - new BigNumber(userGlobalData.availableBorrowsETH.toString()) - .div(usdcPrice.toString()) - .multipliedBy(0.9502) - .toFixed(0) - ); - - await pool - .connect(borrower.signer) - .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); - - //drops HF below 1 - - await oracle.setAssetPrice( - usdc.address, - new BigNumber(usdcPrice.toString()).multipliedBy(1.12).toFixed(0) - ); - - //mints dai to the liquidator - - await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000')); - - //approve protocol to access depositor wallet - await usdc.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const userReserveDataBefore = await helpersContract.getUserReserveData( - usdc.address, - borrower.address - ); - - const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address); - const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); - - const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) - .multipliedBy(0.5) - .toFixed(0); - - await pool.liquidationCall( - weth.address, - usdc.address, - borrower.address, - amountToLiquidate, - true - ); - - const userReserveDataAfter = await helpersContract.getUserReserveData( - usdc.address, - borrower.address - ); - - const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); - - const usdcReserveDataAfter = await helpersContract.getReserveData(usdc.address); - const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); - - const collateralPrice = (await oracle.getAssetPrice(weth.address)).toString(); - const principalPrice = (await oracle.getAssetPrice(usdc.address)).toString(); - - const collateralDecimals = ( - await helpersContract.getReserveConfigurationData(weth.address) - ).decimals.toString(); - const principalDecimals = ( - await helpersContract.getReserveConfigurationData(usdc.address) - ).decimals.toString(); - - const expectedCollateralLiquidated = new BigNumber(principalPrice) - .times(new BigNumber(amountToLiquidate).times(105)) - .times(new BigNumber(10).pow(collateralDecimals)) - .div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals))) - .decimalPlaces(0, BigNumber.ROUND_DOWN); - - expect(userGlobalDataAfter.healthFactor.toString()).to.be.bignumber.gt( - oneEther.toFixed(0), - 'Invalid health factor' - ); - - expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( - new BigNumber(userReserveDataBefore.currentStableDebt.toString()) - .minus(amountToLiquidate) - .toFixed(0), - 'Invalid user borrow balance after liquidation' - ); - - expect(usdcReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(usdcReserveDataBefore.availableLiquidity.toString()) - .plus(amountToLiquidate) - .toFixed(0), - 'Invalid principal available liquidity' - ); - - //the liquidity index of the principal reserve needs to be bigger than the index before - expect(usdcReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( - usdcReserveDataBefore.liquidityIndex.toString(), - 'Invalid liquidity index' - ); - - //the principal APY after a liquidation needs to be lower than the APY before - expect(usdcReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( - usdcReserveDataBefore.liquidityRate.toString(), - 'Invalid liquidity APY' - ); - - expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(ethReserveDataBefore.availableLiquidity.toString()).toFixed(0), - 'Invalid collateral available liquidity' - ); - }); -}); diff --git a/test/liquidation-underlying.spec.ts b/test/liquidation-underlying.spec.ts deleted file mode 100644 index 0e37d331..00000000 --- a/test/liquidation-underlying.spec.ts +++ /dev/null @@ -1,492 +0,0 @@ -import BigNumber from 'bignumber.js'; - -import { DRE, increaseTime } from '../helpers/misc-utils'; -import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../helpers/constants'; -import { convertToCurrencyDecimals } from '../helpers/contracts-helpers'; -import { makeSuite } from './helpers/make-suite'; -import { ProtocolErrors, RateMode } from '../helpers/types'; -import { calcExpectedStableDebtTokenBalance } from './helpers/utils/calculations'; -import { getUserData } from './helpers/utils/helpers'; -import { CommonsConfig } from '../markets/aave/commons'; - -import { parseEther } from 'ethers/lib/utils'; - -const chai = require('chai'); - -const { expect } = chai; - -makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', (testEnv) => { - const { INVALID_HF } = ProtocolErrors; - - before('Before LendingPool liquidation: set config', () => { - BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); - }); - - after('After LendingPool liquidation: reset config', () => { - BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); - }); - - it("It's not possible to liquidate on a non-active collateral or a non active principal", async () => { - const { configurator, weth, pool, users, dai } = testEnv; - const user = users[1]; - await configurator.deactivateReserve(weth.address); - - await expect( - pool.liquidationCall(weth.address, dai.address, user.address, parseEther('1000'), false) - ).to.be.revertedWith('2'); - - await configurator.activateReserve(weth.address); - - await configurator.deactivateReserve(dai.address); - - await expect( - pool.liquidationCall(weth.address, dai.address, user.address, parseEther('1000'), false) - ).to.be.revertedWith('2'); - - await configurator.activateReserve(dai.address); - }); - - it('Deposits WETH, borrows DAI', async () => { - const { dai, weth, users, pool, oracle } = testEnv; - const depositor = users[0]; - const borrower = users[1]; - - //mints DAI to depositor - await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); - - //approve protocol to access depositor wallet - await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - //user 1 deposits 1000 DAI - const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await pool - .connect(depositor.signer) - .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); - //user 2 deposits 1 ETH - const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); - - //mints WETH to borrower - await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); - - //approve protocol to access the borrower wallet - await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - await pool - .connect(borrower.signer) - .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); - - //user 2 borrows - - const userGlobalData = await pool.getUserAccountData(borrower.address); - const daiPrice = await oracle.getAssetPrice(dai.address); - - const amountDAIToBorrow = await convertToCurrencyDecimals( - dai.address, - new BigNumber(userGlobalData.availableBorrowsETH.toString()) - .div(daiPrice.toString()) - .multipliedBy(0.95) - .toFixed(0) - ); - - await pool - .connect(borrower.signer) - .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address); - - const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); - - expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.bignumber.equal( - '8250', - INVALID_HF - ); - }); - - it('Drop the health factor below 1', async () => { - const { dai, weth, users, pool, oracle } = testEnv; - const borrower = users[1]; - - const daiPrice = await oracle.getAssetPrice(dai.address); - - await oracle.setAssetPrice( - dai.address, - new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0) - ); - - const userGlobalData = await pool.getUserAccountData(borrower.address); - - expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( - oneEther.toFixed(0), - INVALID_HF - ); - }); - - it('Liquidates the borrow', async () => { - const { dai, weth, users, pool, oracle, helpersContract } = testEnv; - const liquidator = users[3]; - const borrower = users[1]; - - //mints dai to the liquidator - await dai.connect(liquidator.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); - - //approve protocol to access the liquidator wallet - await dai.connect(liquidator.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); - const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); - - const userReserveDataBefore = await getUserData( - pool, - helpersContract, - dai.address, - borrower.address - ); - - const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); - - await increaseTime(100); - - const tx = await pool - .connect(liquidator.signer) - .liquidationCall(weth.address, dai.address, borrower.address, amountToLiquidate, false); - - const userReserveDataAfter = await getUserData( - pool, - helpersContract, - dai.address, - borrower.address - ); - - const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); - const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); - - const collateralPrice = await oracle.getAssetPrice(weth.address); - const principalPrice = await oracle.getAssetPrice(dai.address); - - const collateralDecimals = ( - await helpersContract.getReserveConfigurationData(weth.address) - ).decimals.toString(); - const principalDecimals = ( - await helpersContract.getReserveConfigurationData(dai.address) - ).decimals.toString(); - - const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) - .times(new BigNumber(amountToLiquidate).times(105)) - .times(new BigNumber(10).pow(collateralDecimals)) - .div( - new BigNumber(collateralPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) - ) - .div(100) - .decimalPlaces(0, BigNumber.ROUND_DOWN); - - if (!tx.blockNumber) { - expect(false, 'Invalid block number'); - return; - } - const txTimestamp = new BigNumber( - (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp - ); - - const stableDebtBeforeTx = calcExpectedStableDebtTokenBalance( - userReserveDataBefore.principalStableDebt, - userReserveDataBefore.stableBorrowRate, - userReserveDataBefore.stableRateLastUpdated, - txTimestamp - ); - - expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( - stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), - 'Invalid user debt after liquidation' - ); - - //the liquidity index of the principal reserve needs to be bigger than the index before - expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( - daiReserveDataBefore.liquidityIndex.toString(), - 'Invalid liquidity index' - ); - - //the principal APY after a liquidation needs to be lower than the APY before - expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( - daiReserveDataBefore.liquidityRate.toString(), - 'Invalid liquidity APY' - ); - - expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(daiReserveDataBefore.availableLiquidity.toString()) - .plus(amountToLiquidate) - .toFixed(0), - 'Invalid principal available liquidity' - ); - - expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) - .minus(expectedCollateralLiquidated) - .toFixed(0), - 'Invalid collateral available liquidity' - ); - }); - - it('User 3 deposits 1000 USDC, user 4 1 WETH, user 4 borrows - drops HF, liquidates the borrow', async () => { - const { usdc, users, pool, oracle, weth, helpersContract } = testEnv; - - const depositor = users[3]; - const borrower = users[4]; - const liquidator = users[5]; - - //mints USDC to depositor - await usdc - .connect(depositor.signer) - .mint(await convertToCurrencyDecimals(usdc.address, '1000')); - - //approve protocol to access depositor wallet - await usdc.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - //depositor deposits 1000 USDC - const amountUSDCtoDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); - - await pool - .connect(depositor.signer) - .deposit(usdc.address, amountUSDCtoDeposit, depositor.address, '0'); - - //borrower deposits 1 ETH - const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); - - //mints WETH to borrower - await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); - - //approve protocol to access the borrower wallet - await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - await pool - .connect(borrower.signer) - .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); - - //borrower borrows - const userGlobalData = await pool.getUserAccountData(borrower.address); - - const usdcPrice = await oracle.getAssetPrice(usdc.address); - - const amountUSDCToBorrow = await convertToCurrencyDecimals( - usdc.address, - new BigNumber(userGlobalData.availableBorrowsETH.toString()) - .div(usdcPrice.toString()) - .multipliedBy(0.9502) - .toFixed(0) - ); - - await pool - .connect(borrower.signer) - .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); - - //drops HF below 1 - await oracle.setAssetPrice( - usdc.address, - new BigNumber(usdcPrice.toString()).multipliedBy(1.12).toFixed(0) - ); - - //mints dai to the liquidator - - await usdc - .connect(liquidator.signer) - .mint(await convertToCurrencyDecimals(usdc.address, '1000')); - - //approve protocol to access depositor wallet - await usdc.connect(liquidator.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const userReserveDataBefore = await helpersContract.getUserReserveData( - usdc.address, - borrower.address - ); - - const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address); - const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); - - const amountToLiquidate = DRE.ethers.BigNumber.from( - userReserveDataBefore.currentStableDebt.toString() - ) - .div(2) - .toString(); - - await pool - .connect(liquidator.signer) - .liquidationCall(weth.address, usdc.address, borrower.address, amountToLiquidate, false); - - const userReserveDataAfter = await helpersContract.getUserReserveData( - usdc.address, - borrower.address - ); - - const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); - - const usdcReserveDataAfter = await helpersContract.getReserveData(usdc.address); - const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); - - const collateralPrice = await oracle.getAssetPrice(weth.address); - const principalPrice = await oracle.getAssetPrice(usdc.address); - - const collateralDecimals = ( - await helpersContract.getReserveConfigurationData(weth.address) - ).decimals.toString(); - const principalDecimals = ( - await helpersContract.getReserveConfigurationData(usdc.address) - ).decimals.toString(); - - const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) - .times(new BigNumber(amountToLiquidate).times(105)) - .times(new BigNumber(10).pow(collateralDecimals)) - .div( - new BigNumber(collateralPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) - ) - .div(100) - .decimalPlaces(0, BigNumber.ROUND_DOWN); - - expect(userGlobalDataAfter.healthFactor.toString()).to.be.bignumber.gt( - oneEther.toFixed(0), - 'Invalid health factor' - ); - - expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( - new BigNumber(userReserveDataBefore.currentStableDebt.toString()) - .minus(amountToLiquidate) - .toFixed(0), - 'Invalid user borrow balance after liquidation' - ); - - //the liquidity index of the principal reserve needs to be bigger than the index before - expect(usdcReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( - usdcReserveDataBefore.liquidityIndex.toString(), - 'Invalid liquidity index' - ); - - //the principal APY after a liquidation needs to be lower than the APY before - expect(usdcReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( - usdcReserveDataBefore.liquidityRate.toString(), - 'Invalid liquidity APY' - ); - - expect(usdcReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(usdcReserveDataBefore.availableLiquidity.toString()) - .plus(amountToLiquidate) - .toFixed(0), - 'Invalid principal available liquidity' - ); - - expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) - .minus(expectedCollateralLiquidated) - .toFixed(0), - 'Invalid collateral available liquidity' - ); - }); - - it('User 4 deposits 10 AAVE - drops HF, liquidates the AAVE, which results on a lower amount being liquidated', async () => { - const { aave, usdc, users, pool, oracle, helpersContract } = testEnv; - - const depositor = users[3]; - const borrower = users[4]; - const liquidator = users[5]; - - //mints AAVE to borrower - await aave.connect(borrower.signer).mint(await convertToCurrencyDecimals(aave.address, '10')); - - //approve protocol to access the borrower wallet - await aave.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - //borrower deposits 10 AAVE - const amountToDeposit = await convertToCurrencyDecimals(aave.address, '10'); - - await pool - .connect(borrower.signer) - .deposit(aave.address, amountToDeposit, borrower.address, '0'); - const usdcPrice = await oracle.getAssetPrice(usdc.address); - - //drops HF below 1 - await oracle.setAssetPrice( - usdc.address, - new BigNumber(usdcPrice.toString()).multipliedBy(1.14).toFixed(0) - ); - - //mints usdc to the liquidator - await usdc - .connect(liquidator.signer) - .mint(await convertToCurrencyDecimals(usdc.address, '1000')); - - //approve protocol to access depositor wallet - await usdc.connect(liquidator.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const userReserveDataBefore = await helpersContract.getUserReserveData( - usdc.address, - borrower.address - ); - - const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address); - const aaveReserveDataBefore = await helpersContract.getReserveData(aave.address); - - const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) - .div(2) - .decimalPlaces(0, BigNumber.ROUND_DOWN) - .toFixed(0); - - const collateralPrice = await oracle.getAssetPrice(aave.address); - const principalPrice = await oracle.getAssetPrice(usdc.address); - - await pool - .connect(liquidator.signer) - .liquidationCall(aave.address, usdc.address, borrower.address, amountToLiquidate, false); - - const userReserveDataAfter = await helpersContract.getUserReserveData( - usdc.address, - borrower.address - ); - - const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); - - const usdcReserveDataAfter = await helpersContract.getReserveData(usdc.address); - const aaveReserveDataAfter = await helpersContract.getReserveData(aave.address); - - const aaveConfiguration = await helpersContract.getReserveConfigurationData(aave.address); - const collateralDecimals = aaveConfiguration.decimals.toString(); - const liquidationBonus = aaveConfiguration.liquidationBonus.toString(); - - const principalDecimals = ( - await helpersContract.getReserveConfigurationData(usdc.address) - ).decimals.toString(); - - const expectedCollateralLiquidated = oneEther.multipliedBy('10'); - - const expectedPrincipal = new BigNumber(collateralPrice.toString()) - .times(expectedCollateralLiquidated) - .times(new BigNumber(10).pow(principalDecimals)) - .div( - new BigNumber(principalPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) - ) - .times(10000) - .div(liquidationBonus.toString()) - .decimalPlaces(0, BigNumber.ROUND_DOWN); - - expect(userGlobalDataAfter.healthFactor.toString()).to.be.bignumber.gt( - oneEther.toFixed(0), - 'Invalid health factor' - ); - - expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( - new BigNumber(userReserveDataBefore.currentStableDebt.toString()) - .minus(expectedPrincipal) - .toFixed(0), - 'Invalid user borrow balance after liquidation' - ); - - expect(usdcReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(usdcReserveDataBefore.availableLiquidity.toString()) - .plus(expectedPrincipal) - .toFixed(0), - 'Invalid principal available liquidity' - ); - - expect(aaveReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(aaveReserveDataBefore.availableLiquidity.toString()) - .minus(expectedCollateralLiquidated) - .toFixed(0), - 'Invalid collateral available liquidity' - ); - }); -}); diff --git a/test/mainnet/check-list.spec.ts b/test/mainnet/check-list.spec.ts deleted file mode 100644 index 99020fa2..00000000 --- a/test/mainnet/check-list.spec.ts +++ /dev/null @@ -1,366 +0,0 @@ -import { MAX_UINT_AMOUNT } from '../../helpers/constants'; -import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; -import { makeSuite, TestEnv } from '../helpers/make-suite'; -import { parseEther } from 'ethers/lib/utils'; -import { DRE, waitForTx } from '../../helpers/misc-utils'; -import { BigNumber } from 'ethers'; -import { getStableDebtToken, getVariableDebtToken } from '../../helpers/contracts-getters'; -import { deploySelfdestructTransferMock } from '../../helpers/contracts-deployments'; -import { IUniswapV2Router02Factory } from '../../types/IUniswapV2Router02Factory'; - -const { expect } = require('chai'); - -const UNISWAP_ROUTER = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'; - -makeSuite('Mainnet Check list', (testEnv: TestEnv) => { - const zero = BigNumber.from('0'); - const depositSize = parseEther('5'); - const daiSize = parseEther('10000'); - it('Deposit WETH', async () => { - const { users, wethGateway, aWETH, pool } = testEnv; - - const user = users[1]; - - // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); - - const aTokensBalance = await aWETH.balanceOf(user.address); - - expect(aTokensBalance).to.be.gt(zero); - expect(aTokensBalance).to.be.gte(depositSize); - }); - - it('Withdraw WETH - Partial', async () => { - const { users, wethGateway, aWETH, pool } = testEnv; - - const user = users[1]; - const priorEthersBalance = await user.signer.getBalance(); - const aTokensBalance = await aWETH.balanceOf(user.address); - - expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.'); - - // Partially withdraw native ETH - const partialWithdraw = await convertToCurrencyDecimals(aWETH.address, '2'); - - // Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether - const approveTx = await aWETH - .connect(user.signer) - .approve(wethGateway.address, MAX_UINT_AMOUNT); - const { gasUsed: approveGas } = await waitForTx(approveTx); - - // Partial Withdraw and send native Ether to user - const { gasUsed: withdrawGas } = await waitForTx( - await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) - ); - - const afterPartialEtherBalance = await user.signer.getBalance(); - const afterPartialATokensBalance = await aWETH.balanceOf(user.address); - const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice); - - expect(afterPartialEtherBalance).to.be.equal( - priorEthersBalance.add(partialWithdraw).sub(gasCosts), - 'User ETHER balance should contain the partial withdraw' - ); - expect(afterPartialATokensBalance).to.be.equal( - aTokensBalance.sub(partialWithdraw), - 'User aWETH balance should be substracted' - ); - }); - - it('Withdraw WETH - Full', async () => { - const { users, aWETH, wethGateway, pool } = testEnv; - - const user = users[1]; - const priorEthersBalance = await user.signer.getBalance(); - const aTokensBalance = await aWETH.balanceOf(user.address); - - expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.'); - - // Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether - const approveTx = await aWETH - .connect(user.signer) - .approve(wethGateway.address, MAX_UINT_AMOUNT); - const { gasUsed: approveGas } = await waitForTx(approveTx); - - // Full withdraw - const { gasUsed: withdrawGas } = await waitForTx( - await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) - ); - - const afterFullEtherBalance = await user.signer.getBalance(); - const afterFullATokensBalance = await aWETH.balanceOf(user.address); - const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice); - - expect(afterFullEtherBalance).to.be.eq( - priorEthersBalance.add(aTokensBalance).sub(gasCosts), - 'User ETHER balance should contain the full withdraw' - ); - expect(afterFullATokensBalance).to.be.eq(0, 'User aWETH balance should be zero'); - }); - - it('Borrow stable WETH and Full Repay with ETH', async () => { - const { users, wethGateway, aWETH, dai, aDai, weth, pool, helpersContract } = testEnv; - const borrowSize = parseEther('1'); - const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); - const user = users[1]; - - const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - weth.address - ); - - const stableDebtToken = await getStableDebtToken(stableDebtTokenAddress); - - // Deposit 10000 DAI - await dai.connect(user.signer).mint(daiSize); - await dai.connect(user.signer).approve(pool.address, daiSize); - await pool.connect(user.signer).deposit(dai.address, daiSize, user.address, '0'); - - const aTokensBalance = await aDai.balanceOf(user.address); - - expect(aTokensBalance).to.be.gt(zero); - expect(aTokensBalance).to.be.gte(daiSize); - - // Borrow WETH with WETH as collateral - await waitForTx( - await pool.connect(user.signer).borrow(weth.address, borrowSize, '1', '0', user.address) - ); - - const debtBalance = await stableDebtToken.balanceOf(user.address); - - expect(debtBalance).to.be.gt(zero); - - // Full Repay WETH with native ETH - await waitForTx( - await wethGateway - .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) - ); - - const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); - expect(debtBalanceAfterRepay).to.be.eq(zero); - }); - - it('Borrow variable WETH and Full Repay with ETH', async () => { - const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; - const borrowSize = parseEther('1'); - const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); - const user = users[1]; - - const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - weth.address - ); - - const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); - - // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); - - const aTokensBalance = await aWETH.balanceOf(user.address); - - expect(aTokensBalance).to.be.gt(zero); - expect(aTokensBalance).to.be.gte(depositSize); - - // Borrow WETH with WETH as collateral - await waitForTx( - await pool.connect(user.signer).borrow(weth.address, borrowSize, '2', '0', user.address) - ); - - const debtBalance = await varDebtToken.balanceOf(user.address); - - expect(debtBalance).to.be.gt(zero); - - // Partial Repay WETH loan with native ETH - const partialPayment = repaySize.div(2); - await waitForTx( - await wethGateway - .connect(user.signer) - .repayETH(partialPayment, '2', user.address, { value: partialPayment }) - ); - - const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); - expect(debtBalanceAfterPartialRepay).to.be.lt(debtBalance); - - // Full Repay WETH loan with native ETH - await waitForTx( - await wethGateway - .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) - ); - const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); - expect(debtBalanceAfterFullRepay).to.be.eq(zero); - }); - - it('Borrow ETH via delegateApprove ETH and repays back', async () => { - const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; - const borrowSize = parseEther('1'); - const user = users[2]; - const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - weth.address - ); - const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); - - const priorDebtBalance = await varDebtToken.balanceOf(user.address); - expect(priorDebtBalance).to.be.eq(zero); - - // Deposit WETH with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); - - const aTokensBalance = await aWETH.balanceOf(user.address); - - expect(aTokensBalance).to.be.gt(zero); - expect(aTokensBalance).to.be.gte(depositSize); - - // Delegates borrowing power of WETH to WETHGateway - await waitForTx( - await varDebtToken.connect(user.signer).approveDelegation(wethGateway.address, borrowSize) - ); - - // Borrows ETH with WETH as collateral - await waitForTx(await wethGateway.connect(user.signer).borrowETH(borrowSize, '2', '0')); - - const debtBalance = await varDebtToken.balanceOf(user.address); - - expect(debtBalance).to.be.gt(zero); - - // Full Repay WETH loan with native ETH - await waitForTx( - await wethGateway - .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) - ); - const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); - expect(debtBalanceAfterFullRepay).to.be.eq(zero); - }); - - it('Should revert if receiver function receives Ether if not WETH', async () => { - const { users, wethGateway } = testEnv; - const user = users[0]; - const amount = parseEther('1'); - - // Call receiver function (empty data + value) - await expect( - user.signer.sendTransaction({ - to: wethGateway.address, - value: amount, - gasLimit: DRE.network.config.gas, - }) - ).to.be.revertedWith('Receive not allowed'); - }); - - it('Should revert if fallback functions is called with Ether', async () => { - const { users, wethGateway } = testEnv; - const user = users[0]; - const amount = parseEther('1'); - const fakeABI = ['function wantToCallFallback()']; - const abiCoder = new DRE.ethers.utils.Interface(fakeABI); - const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []); - - // Call fallback function with value - await expect( - user.signer.sendTransaction({ - to: wethGateway.address, - data: fakeMethodEncoded, - value: amount, - gasLimit: DRE.network.config.gas, - }) - ).to.be.revertedWith('Fallback not allowed'); - }); - - it('Should revert if fallback functions is called', async () => { - const { users, wethGateway } = testEnv; - const user = users[0]; - - const fakeABI = ['function wantToCallFallback()']; - const abiCoder = new DRE.ethers.utils.Interface(fakeABI); - const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []); - - // Call fallback function without value - await expect( - user.signer.sendTransaction({ - to: wethGateway.address, - data: fakeMethodEncoded, - gasLimit: DRE.network.config.gas, - }) - ).to.be.revertedWith('Fallback not allowed'); - }); - - it('Getters should retrieve correct state', async () => { - const { aWETH, weth, pool, wethGateway } = testEnv; - - const WETHAddress = await wethGateway.getWETHAddress(); - const aWETHAddress = await wethGateway.getAWETHAddress(); - const poolAddress = await wethGateway.getLendingPoolAddress(); - - expect(WETHAddress).to.be.equal(weth.address); - expect(aWETHAddress).to.be.equal(aWETH.address); - expect(poolAddress).to.be.equal(pool.address); - }); - - it('Owner can do emergency token recovery', async () => { - const { users, weth, dai, wethGateway, deployer } = testEnv; - const user = users[0]; - const amount = parseEther('1'); - - const uniswapRouter = IUniswapV2Router02Factory.connect(UNISWAP_ROUTER, user.signer); - await uniswapRouter.swapETHForExactTokens( - amount, // 1 DAI - [weth.address, dai.address], // Uniswap paths WETH - DAI - user.address, - (await DRE.ethers.provider.getBlock('latest')).timestamp + 300, - { - value: amount, // 1 Ether, we get refund of the unneeded Ether to buy 1 DAI - } - ); - const daiBalanceAfterMint = await dai.balanceOf(user.address); - - await dai.connect(user.signer).transfer(wethGateway.address, amount); - const daiBalanceAfterBadTransfer = await dai.balanceOf(user.address); - expect(daiBalanceAfterBadTransfer).to.be.eq( - daiBalanceAfterMint.sub(amount), - 'User should have lost the funds here.' - ); - - await wethGateway - .connect(deployer.signer) - .emergencyTokenTransfer(dai.address, user.address, amount); - const daiBalanceAfterRecovery = await dai.balanceOf(user.address); - - expect(daiBalanceAfterRecovery).to.be.eq( - daiBalanceAfterMint, - 'User should recover the funds due emergency token transfer' - ); - }); - - it('Owner can do emergency native ETH recovery', async () => { - const { users, wethGateway, deployer } = testEnv; - const user = users[0]; - const amount = parseEther('1'); - const userBalancePriorCall = await user.signer.getBalance(); - - // Deploy contract with payable selfdestruct contract - const selfdestructContract = await deploySelfdestructTransferMock(); - - // Selfdestruct the mock, pointing to WETHGateway address - const callTx = await selfdestructContract - .connect(user.signer) - .destroyAndTransfer(wethGateway.address, { value: amount }); - const { gasUsed } = await waitForTx(callTx); - const gasFees = gasUsed.mul(callTx.gasPrice); - const userBalanceAfterCall = await user.signer.getBalance(); - - expect(userBalanceAfterCall).to.be.eq(userBalancePriorCall.sub(amount).sub(gasFees), ''); - ('User should have lost the funds'); - - // Recover the funds from the contract and sends back to the user - await wethGateway.connect(deployer.signer).emergencyEtherTransfer(user.address, amount); - - const userBalanceAfterRecovery = await user.signer.getBalance(); - const wethGatewayAfterRecovery = await DRE.ethers.provider.getBalance(wethGateway.address); - - expect(userBalanceAfterRecovery).to.be.eq( - userBalancePriorCall.sub(gasFees), - 'User should recover the funds due emergency eth transfer.' - ); - expect(wethGatewayAfterRecovery).to.be.eq('0', 'WETHGateway ether balance should be zero.'); - }); -}); diff --git a/test/pausable-functions.spec.ts b/test/pausable-functions.spec.ts deleted file mode 100644 index 2ac975ac..00000000 --- a/test/pausable-functions.spec.ts +++ /dev/null @@ -1,330 +0,0 @@ -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { ProtocolErrors, RateMode } from '../helpers/types'; -import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../helpers/constants'; -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'); - -makeSuite('Pausable Pool', (testEnv: TestEnv) => { - let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver; - - const { - LP_IS_PAUSED, - INVALID_FROM_BALANCE_AFTER_TRANSFER, - INVALID_TO_BALANCE_AFTER_TRANSFER, - } = ProtocolErrors; - - before(async () => { - _mockFlashLoanReceiver = await getMockFlashLoanReceiver(); - }); - - it('User 0 deposits 1000 DAI. Configurator pauses pool. Transfers to user 1 reverts. Configurator unpauses the network and next transfer succees', async () => { - const { users, pool, dai, aDai, configurator } = testEnv; - - const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await dai.connect(users[0].signer).mint(amountDAItoDeposit); - - // user 0 deposits 1000 DAI - await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - await pool - .connect(users[0].signer) - .deposit(dai.address, amountDAItoDeposit, users[0].address, '0'); - - const user0Balance = await aDai.balanceOf(users[0].address); - const user1Balance = await aDai.balanceOf(users[1].address); - - // Configurator pauses the pool - await configurator.connect(users[1].signer).setPoolPause(true); - - // User 0 tries the transfer to User 1 - await expect( - aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit) - ).to.revertedWith(LP_IS_PAUSED); - - const pausedFromBalance = await aDai.balanceOf(users[0].address); - const pausedToBalance = await aDai.balanceOf(users[1].address); - - expect(pausedFromBalance).to.be.equal( - user0Balance.toString(), - INVALID_TO_BALANCE_AFTER_TRANSFER - ); - expect(pausedToBalance.toString()).to.be.equal( - user1Balance.toString(), - INVALID_FROM_BALANCE_AFTER_TRANSFER - ); - - // Configurator unpauses the pool - await configurator.connect(users[1].signer).setPoolPause(false); - - // User 0 succeeds transfer to User 1 - await aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit); - - const fromBalance = await aDai.balanceOf(users[0].address); - const toBalance = await aDai.balanceOf(users[1].address); - - expect(fromBalance.toString()).to.be.equal( - user0Balance.sub(amountDAItoDeposit), - INVALID_FROM_BALANCE_AFTER_TRANSFER - ); - expect(toBalance.toString()).to.be.equal( - user1Balance.add(amountDAItoDeposit), - INVALID_TO_BALANCE_AFTER_TRANSFER - ); - }); - - it('Deposit', async () => { - const { users, pool, dai, aDai, configurator } = testEnv; - - const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await dai.connect(users[0].signer).mint(amountDAItoDeposit); - - // user 0 deposits 1000 DAI - await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - // Configurator pauses the pool - await configurator.connect(users[1].signer).setPoolPause(true); - await expect( - pool.connect(users[0].signer).deposit(dai.address, amountDAItoDeposit, users[0].address, '0') - ).to.revertedWith(LP_IS_PAUSED); - - // Configurator unpauses the pool - await configurator.connect(users[1].signer).setPoolPause(false); - }); - - it('Withdraw', async () => { - const { users, pool, dai, aDai, configurator } = testEnv; - - const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await dai.connect(users[0].signer).mint(amountDAItoDeposit); - - // user 0 deposits 1000 DAI - await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - await pool - .connect(users[0].signer) - .deposit(dai.address, amountDAItoDeposit, users[0].address, '0'); - - // Configurator pauses the pool - await configurator.connect(users[1].signer).setPoolPause(true); - - // user tries to burn - await expect( - pool.connect(users[0].signer).withdraw(dai.address, amountDAItoDeposit, users[0].address) - ).to.revertedWith(LP_IS_PAUSED); - - // Configurator unpauses the pool - await configurator.connect(users[1].signer).setPoolPause(false); - }); - - it('Borrow', async () => { - const { pool, dai, users, configurator } = testEnv; - - const user = users[1]; - // Pause the pool - await configurator.connect(users[1].signer).setPoolPause(true); - - // Try to execute liquidation - await expect( - pool.connect(user.signer).borrow(dai.address, '1', '1', '0', user.address) - ).revertedWith(LP_IS_PAUSED); - - // Unpause the pool - await configurator.connect(users[1].signer).setPoolPause(false); - }); - - it('Repay', async () => { - const { pool, dai, users, configurator } = testEnv; - - const user = users[1]; - // Pause the pool - await configurator.connect(users[1].signer).setPoolPause(true); - - // Try to execute liquidation - await expect(pool.connect(user.signer).repay(dai.address, '1', '1', user.address)).revertedWith( - LP_IS_PAUSED - ); - - // Unpause the pool - await configurator.connect(users[1].signer).setPoolPause(false); - }); - - it('Flash loan', async () => { - const { dai, pool, weth, users, configurator } = testEnv; - - const caller = users[3]; - - const flashAmount = parseEther('0.8'); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - // Pause pool - await configurator.connect(users[1].signer).setPoolPause(true); - - await expect( - pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [flashAmount], - [1], - caller.address, - '0x10', - '0' - ) - ).revertedWith(LP_IS_PAUSED); - - // Unpause pool - await configurator.connect(users[1].signer).setPoolPause(false); - }); - - it('Liquidation call', async () => { - const { users, pool, usdc, oracle, weth, configurator, helpersContract } = testEnv; - const depositor = users[3]; - const borrower = users[4]; - - //mints USDC to depositor - await usdc - .connect(depositor.signer) - .mint(await convertToCurrencyDecimals(usdc.address, '1000')); - - //approve protocol to access depositor wallet - await usdc.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - //user 3 deposits 1000 USDC - const amountUSDCtoDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); - - await pool - .connect(depositor.signer) - .deposit(usdc.address, amountUSDCtoDeposit, depositor.address, '0'); - - //user 4 deposits 1 ETH - const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); - - //mints WETH to borrower - await weth.connect(borrower.signer).mint(amountETHtoDeposit); - - //approve protocol to access borrower wallet - await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - await pool - .connect(borrower.signer) - .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); - - //user 4 borrows - const userGlobalData = await pool.getUserAccountData(borrower.address); - - const usdcPrice = await oracle.getAssetPrice(usdc.address); - - const amountUSDCToBorrow = await convertToCurrencyDecimals( - usdc.address, - new BigNumber(userGlobalData.availableBorrowsETH.toString()) - .div(usdcPrice.toString()) - .multipliedBy(0.9502) - .toFixed(0) - ); - - await pool - .connect(borrower.signer) - .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); - - // Drops HF below 1 - await oracle.setAssetPrice( - usdc.address, - new BigNumber(usdcPrice.toString()).multipliedBy(1.2).toFixed(0) - ); - - //mints dai to the liquidator - await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000')); - await usdc.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const userReserveDataBefore = await helpersContract.getUserReserveData( - usdc.address, - borrower.address - ); - - const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) - .multipliedBy(0.5) - .toFixed(0); - - // Pause pool - await configurator.connect(users[1].signer).setPoolPause(true); - - // Do liquidation - await expect( - pool.liquidationCall(weth.address, usdc.address, borrower.address, amountToLiquidate, true) - ).revertedWith(LP_IS_PAUSED); - - // Unpause pool - await configurator.connect(users[1].signer).setPoolPause(false); - }); - - it('SwapBorrowRateMode', async () => { - const { pool, weth, dai, usdc, users, configurator } = testEnv; - const user = users[1]; - const amountWETHToDeposit = parseEther('10'); - const amountDAIToDeposit = parseEther('120'); - const amountToBorrow = parseUnits('65', 6); - - await weth.connect(user.signer).mint(amountWETHToDeposit); - await weth.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - await pool.connect(user.signer).deposit(weth.address, amountWETHToDeposit, user.address, '0'); - - await dai.connect(user.signer).mint(amountDAIToDeposit); - await dai.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - await pool.connect(user.signer).deposit(dai.address, amountDAIToDeposit, user.address, '0'); - - await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0, user.address); - - // Pause pool - await configurator.connect(users[1].signer).setPoolPause(true); - - // Try to repay - await expect( - pool.connect(user.signer).swapBorrowRateMode(usdc.address, RateMode.Stable) - ).revertedWith(LP_IS_PAUSED); - - // Unpause pool - await configurator.connect(users[1].signer).setPoolPause(false); - }); - - it('RebalanceStableBorrowRate', async () => { - const { pool, dai, users, configurator } = testEnv; - const user = users[1]; - // Pause pool - await configurator.connect(users[1].signer).setPoolPause(true); - - await expect( - pool.connect(user.signer).rebalanceStableBorrowRate(dai.address, user.address) - ).revertedWith(LP_IS_PAUSED); - - // Unpause pool - await configurator.connect(users[1].signer).setPoolPause(false); - }); - - it('setUserUseReserveAsCollateral', async () => { - const { pool, weth, users, configurator } = testEnv; - const user = users[1]; - - const amountWETHToDeposit = parseEther('1'); - await weth.connect(user.signer).mint(amountWETHToDeposit); - await weth.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - await pool.connect(user.signer).deposit(weth.address, amountWETHToDeposit, user.address, '0'); - - // Pause pool - await configurator.connect(users[1].signer).setPoolPause(true); - - await expect( - pool.connect(user.signer).setUserUseReserveAsCollateral(weth.address, false) - ).revertedWith(LP_IS_PAUSED); - - // Unpause pool - await configurator.connect(users[1].signer).setPoolPause(false); - }); -}); diff --git a/test/pool-modifiers.spec.ts b/test/pool-modifiers.spec.ts deleted file mode 100644 index fb915b15..00000000 --- a/test/pool-modifiers.spec.ts +++ /dev/null @@ -1,241 +0,0 @@ -// import {iATokenBase, iAssetsWithoutETH, ITestEnvWithoutInstances, RateMode} from '../utils/types'; -// import { -// LendingPoolConfiguratorInstance, -// LendingPoolInstance, -// ATokenInstance, -// LendingPoolCoreInstance, -// MintableERC20Instance, -// } from '../utils/typechain-types/truffle-contracts'; -// import {testEnvProviderWithoutInstances} from '../utils/truffle/dlp-tests-env'; -// import {oneEther, ETHEREUM_ADDRESS} from '../utils/constants'; -// import {convertToCurrencyDecimals} from '../utils/misc-utils'; - -// const expectRevert = require('@openzeppelin/test-helpers').expectRevert; - -// contract('LendingPool: Modifiers', async ([deployer, ...users]) => { -// let _testEnvProvider: ITestEnvWithoutInstances; -// let _lendingPoolConfiguratorInstance: LendingPoolConfiguratorInstance; -// let _lendingPoolInstance: LendingPoolInstance; -// let _lendingPoolCoreInstance: LendingPoolCoreInstance; -// let _aTokenInstances: iATokenBase; -// let _tokenInstances: iAssetsWithoutETH; - -// before('Initializing LendingPool test variables', async () => { -// console.time('setup-test'); -// _testEnvProvider = await testEnvProviderWithoutInstances(artifacts, [deployer, ...users]); - -// const { -// getAllAssetsInstances, -// getLendingPoolInstance, -// getLendingPoolCoreInstance, -// getLendingPoolConfiguratorInstance, -// getATokenInstances, -// } = _testEnvProvider; -// const instances = await Promise.all([ -// getLendingPoolInstance(), -// getLendingPoolCoreInstance(), -// getLendingPoolConfiguratorInstance(), -// getATokenInstances(), -// getAllAssetsInstances(), -// ]); - -// _lendingPoolInstance = instances[0]; -// _lendingPoolCoreInstance = instances[1]; -// _lendingPoolConfiguratorInstance = instances[2]; - -// _aTokenInstances = instances[3]; -// _tokenInstances = instances[4]; -// console.timeEnd('setup-test'); -// }); - -// it('Tries to deposit in an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.deposit(deployer, '1', '0'), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to invoke redeemUnderlying on an reserve, from a non-aToken address', async () => { -// await expectRevert( -// _lendingPoolInstance.redeemUnderlying(ETHEREUM_ADDRESS, deployer, '1', '0'), -// 'The caller of this function can only be the aToken contract of this reserve' -// ); -// }); - -// it('Tries to borrow from an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.borrow(deployer, '1', '0', RateMode.Stable), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to repay in an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.repay(deployer, '1', deployer), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to swapBorrowRateMode on an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.swapBorrowRateMode(deployer), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to rebalanceStableBorrowRate on an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.rebalanceStableBorrowRate(deployer, deployer), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to setUserUseReserveAsCollateral on an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.setUserUseReserveAsCollateral(deployer, true), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to invoke liquidationCall on an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.liquidationCall(ETHEREUM_ADDRESS, deployer, deployer, '1', false), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to invoke liquidationCall on an inactive collateral', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.liquidationCall(deployer, ETHEREUM_ADDRESS, deployer, '1', false), -// 'Action requires an active reserve' -// ); -// }); - -// it('Freezes the ETH reserve', async () => { -// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS); -// }); - -// it('tries to deposit in a freezed reserve', async () => { -// await expectRevert( -// _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, '1', '0'), -// 'Action requires an unfreezed reserve' -// ); -// }); - -// it('tries to borrow from a freezed reserve', async () => { -// await expectRevert( -// _lendingPoolInstance.borrow(ETHEREUM_ADDRESS, '1', '0', '0'), -// 'Action requires an unfreezed reserve' -// ); -// }); - -// it('tries to swap interest rate mode in a freezed reserve', async () => { -// await expectRevert( -// _lendingPoolInstance.swapBorrowRateMode(ETHEREUM_ADDRESS), -// 'Action requires an unfreezed reserve' -// ); -// }); - -// it('tries to disable as collateral a freezed reserve', async () => { -// await expectRevert( -// _lendingPoolInstance.setUserUseReserveAsCollateral(ETHEREUM_ADDRESS, false), -// 'Action requires an unfreezed reserve' -// ); -// }); - -// it('unfreezes the reserve, user deposits 1 ETH, freezes the reserve, check that the user can redeem', async () => { -// const {aWETH} = _aTokenInstances; - -// //unfreezes the reserve -// await _lendingPoolConfiguratorInstance.unfreezeReserve(ETHEREUM_ADDRESS); - -// //deposit 1 ETH -// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, oneEther, '0', { -// value: oneEther.toString(), -// }); - -// //freezes the reserve -// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS); - -// const balance = await aWETH.balanceOf(deployer); - -// await aWETH.redeem(balance); -// }); - -// it('unfreezes the reserve, user 0 deposits 100 DAI, user 1 deposits 1 ETH and borrows 50 DAI, freezes the reserve, checks that the user 1 can repay', async () => { -// const {aWETH, aDAI} = _aTokenInstances; -// const {DAI} = _tokenInstances; - -// //unfreezes the reserve -// await _lendingPoolConfiguratorInstance.unfreezeReserve(ETHEREUM_ADDRESS); - -// const amountDAI = await convertToCurrencyDecimals(DAI.address, '100'); - -// //user 0 deposits 100 DAI -// await DAI.mint(amountDAI, {from: users[0]}); - -// await DAI.approve(_lendingPoolCoreInstance.address, amountDAI, {from: users[0]}); - -// await _lendingPoolInstance.deposit(DAI.address, amountDAI, '0', {from: users[0]}); - -// //user 1 deposits 1 ETH -// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, oneEther, '0', { -// from: users[1], -// value: oneEther.toString(), -// }); - -// const amountDAIToBorrow = await convertToCurrencyDecimals(DAI.address, '10'); - -// //user 1 borrows 10 DAI -// await _lendingPoolInstance.borrow(DAI.address, amountDAIToBorrow, RateMode.Stable, '0', { -// from: users[1], -// }); - -// //freezes the reserve -// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS); - -// //user 1 repays 1 DAI -// await DAI.approve(_lendingPoolCoreInstance.address, amountDAIToBorrow, {from: users[1]}); - -// await _lendingPoolInstance.repay(DAI.address, oneEther, users[1], {from: users[1]}); -// }); - -// it('Check that liquidationCall can be executed on a freezed reserve', async () => { -// const {aWETH, aDAI} = _aTokenInstances; -// const {DAI} = _tokenInstances; - -// //user 2 tries to liquidate - -// await expectRevert( -// _lendingPoolInstance.liquidationCall( -// ETHEREUM_ADDRESS, -// DAI.address, -// users[1], -// oneEther, -// true, -// {from: users[2]} -// ), -// 'Health factor is not below the threshold' -// ); -// }); - -// it('Check that rebalanceStableBorrowRate can be executed on a freezed reserve', async () => { -// const {aWETH, aDAI} = _aTokenInstances; -// const {DAI} = _tokenInstances; - -// //user 2 tries to liquidate - -// await expectRevert( -// _lendingPoolInstance.rebalanceStableBorrowRate(DAI.address, users[1]), -// 'Interest rate rebalance conditions were not met' -// ); -// }); -// }); diff --git a/test/rate-strategy.spec.ts b/test/rate-strategy.spec.ts deleted file mode 100644 index b56c754e..00000000 --- a/test/rate-strategy.spec.ts +++ /dev/null @@ -1,165 +0,0 @@ -// import { -// IReserveParams, -// iAavePoolAssets, -// iAssetsWithoutETH, -// ITestEnvWithoutInstances, -// } from "../utils/types" -// import { - -// LendingPoolAddressesProviderInstance, - -// DefaultReserveInterestRateStrategyInstance, -// MintableERC20Instance, -// } from "../utils/typechain-types/truffle-contracts" -// import { testEnvProviderWithoutInstances} from "../utils/truffle/dlp-tests-env" -// import {RAY} from "../utils/constants" -// import BigNumber from "bignumber.js" - -// const {expect} = require("chai") - -// contract("Interest rate strategy", async ([deployer, ...users]) => { -// let _testEnvProvider: ITestEnvWithoutInstances -// let _strategyInstance: DefaultReserveInterestRateStrategyInstance -// let _tokenInstances: iAssetsWithoutETH -// let _addressesProviderInstance: LendingPoolAddressesProviderInstance -// let _reservesParams: iAavePoolAssets - -// before("Initializing test variables", async () => { -// console.time('setup-test'); -// _testEnvProvider = await testEnvProviderWithoutInstances( -// artifacts, -// [deployer, ...users], -// ) - -// const { -// getAllAssetsInstances, -// getLendingPoolAddressesProviderInstance, -// getAavePoolReservesParams, -// } = _testEnvProvider - -// const instances = await Promise.all([ -// getAllAssetsInstances(), -// getLendingPoolAddressesProviderInstance() -// ]) - -// _tokenInstances = instances[0] -// _addressesProviderInstance = instances[1] -// _reservesParams = await getAavePoolReservesParams() -// console.timeEnd('setup-test'); -// }) - -// it("Deploys a new instance of a DefaultReserveInterestRateStrategy contract", async () => { -// const {DAI: daiInstance} = _tokenInstances - -// const {DAI: daiConfiguration} = _reservesParams - -// const contract: any = await artifacts.require("DefaultReserveInterestRateStrategy") -// const mathLibrary = await artifacts.require("WadRayMath") -// const mathLibraryInstance = await mathLibrary.new() - -// await contract.link("WadRayMath", mathLibraryInstance.address) - -// _strategyInstance = await contract.new( -// daiInstance.address, -// _addressesProviderInstance.address, -// daiConfiguration.baseVariableBorrowRate, -// daiConfiguration.variableRateSlope1, -// daiConfiguration.variableRateSlope2, -// daiConfiguration.stableRateSlope1, -// daiConfiguration.stableRateSlope2, -// ) -// }) - -// it("Checks rates at 0% utilization rate", async () => { -// const {DAI: daiInstance} = _tokenInstances -// const {DAI: daiConfiguration} = _reservesParams -// const data: any = await _strategyInstance.calculateInterestRates( -// daiInstance.address, -// "1000000000000000000", -// "0", -// "0", -// "0", -// ) - -// expect(data.currentLiquidityRate.toString()).to.be.equal("0", "Invalid liquidity rate") -// expect(data.currentStableBorrowRate.toString()).to.be.equal( -// new BigNumber(0.039).times(RAY).toFixed(0), -// "Invalid stable rate", -// ) -// expect(data.currentVariableBorrowRate.toString()).to.be.equal( -// daiConfiguration.baseVariableBorrowRate, -// "Invalid variable rate", -// ) -// }) - -// it("Checks rates at 80% utilization rate", async () => { -// const {DAI: daiInstance} = _tokenInstances -// const {DAI: daiConfiguration} = _reservesParams -// const data: any = await _strategyInstance.calculateInterestRates( -// daiInstance.address, -// "200000000000000000", -// "0", -// "800000000000000000", -// "0", -// ) - -// const expectedVariableRate = new BigNumber(daiConfiguration.baseVariableBorrowRate) -// .plus(daiConfiguration.variableRateSlope1) - -// expect(data.currentLiquidityRate.toString()).to.be.equal( -// expectedVariableRate.times(0.8).toFixed(0), -// "Invalid liquidity rate", -// ) - -// expect(data.currentVariableBorrowRate.toString()).to.be.equal( -// new BigNumber(daiConfiguration.baseVariableBorrowRate) -// .plus(daiConfiguration.variableRateSlope1) -// .toFixed(0), -// "Invalid variable rate", -// ) - -// expect(data.currentStableBorrowRate.toString()).to.be.equal( -// new BigNumber(0.039) -// .times(RAY) -// .plus(daiConfiguration.stableRateSlope1) -// .toFixed(0), -// "Invalid stable rate", -// ) -// }) - -// it("Checks rates at 100% utilization rate", async () => { -// const {DAI: daiInstance} = _tokenInstances -// const {DAI: daiConfiguration} = _reservesParams -// const data: any = await _strategyInstance.calculateInterestRates( -// daiInstance.address, -// "0", -// "0", -// "1000000000000000000", -// "0", -// ) - -// const expectedVariableRate = new BigNumber(daiConfiguration.baseVariableBorrowRate) -// .plus(daiConfiguration.variableRateSlope1) -// .plus(daiConfiguration.variableRateSlope2) -// .toFixed(0) - -// expect(data.currentLiquidityRate.toString()).to.be.equal( -// expectedVariableRate, -// "Invalid liquidity rate", -// ) - -// expect(data.currentVariableBorrowRate.toString()).to.be.equal( -// expectedVariableRate, -// "Invalid variable rate", -// ) - -// expect(data.currentStableBorrowRate.toString()).to.be.equal( -// new BigNumber(0.039) -// .times(RAY) -// .plus(daiConfiguration.stableRateSlope1) -// .plus(daiConfiguration.stableRateSlope2) -// .toFixed(0), -// "Invalid stable rate", -// ) -// }) -// }) diff --git a/test/scenario.spec.ts b/test/scenario.spec.ts deleted file mode 100644 index b7b3c318..00000000 --- a/test/scenario.spec.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { configuration as actionsConfiguration } from './helpers/actions'; -import { configuration as calculationsConfiguration } from './helpers/utils/calculations'; - -import fs from 'fs'; -import BigNumber from 'bignumber.js'; -import { makeSuite } from './helpers/make-suite'; -import { getReservesConfigByPool } from '../helpers/configuration'; -import { AavePools, iAavePoolAssets, IReserveParams } from '../helpers/types'; -import { executeStory } from './helpers/scenario-engine'; - -const scenarioFolder = './test/helpers/scenarios/'; - -const selectedScenarios: string[] = []; - -fs.readdirSync(scenarioFolder).forEach((file) => { - if (selectedScenarios.length > 0 && !selectedScenarios.includes(file)) return; - - const scenario = require(`./helpers/scenarios/${file}`); - - makeSuite(scenario.title, async (testEnv) => { - before('Initializing configuration', async () => { - // Sets BigNumber for this suite, instead of globally - BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); - - actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage - - calculationsConfiguration.reservesParams = >( - getReservesConfigByPool(AavePools.proto) - ); - }); - after('Reset', () => { - // Reset BigNumber - BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); - }); - - for (const story of scenario.stories) { - it(story.description, async function () { - // Retry the test scenarios up to 4 times if an error happens, due erratic HEVM network errors - this.retries(4); - await executeStory(story, testEnv); - }); - } - }); -}); diff --git a/test/stable-rate-economy.spec.ts b/test/stable-rate-economy.spec.ts deleted file mode 100644 index 1c2c156a..00000000 --- a/test/stable-rate-economy.spec.ts +++ /dev/null @@ -1,199 +0,0 @@ -// import { -// LendingPoolInstance, -// LendingPoolCoreInstance, -// MintableERC20Instance, -// ATokenInstance, -// } from "../utils/typechain-types/truffle-contracts" -// import { -// iATokenBase, -// iAssetsWithoutETH, -// ITestEnvWithoutInstances, -// RateMode, -// } from "../utils/types" -// import { -// APPROVAL_AMOUNT_LENDING_POOL_CORE, -// ETHEREUM_ADDRESS, -// } from "../utils/constants" -// import { testEnvProviderWithoutInstances} from "../utils/truffle/dlp-tests-env" -// import {convertToCurrencyDecimals} from "../utils/misc-utils" - -// const expectRevert = require("@openzeppelin/test-helpers").expectRevert - -// contract("LendingPool - stable rate economy tests", async ([deployer, ...users]) => { -// let _testEnvProvider: ITestEnvWithoutInstances -// let _lendingPoolInstance: LendingPoolInstance -// let _lendingPoolCoreInstance: LendingPoolCoreInstance -// let _aTokenInstances: iATokenBase -// let _tokenInstances: iAssetsWithoutETH - -// let _daiAddress: string - -// let _depositorAddress: string -// let _borrowerAddress: string - -// let _web3: Web3 - -// before("Initializing LendingPool test variables", async () => { -// console.time('setup-test'); -// _testEnvProvider = await testEnvProviderWithoutInstances( -// artifacts, -// [deployer, ...users] -// ) - -// const { -// getWeb3, -// getAllAssetsInstances, -// getFirstBorrowerAddressOnTests, -// getFirstDepositorAddressOnTests, -// getLendingPoolInstance, -// getLendingPoolCoreInstance, -// getATokenInstances -// } = _testEnvProvider - -// const instances = await Promise.all([ -// getLendingPoolInstance(), -// getLendingPoolCoreInstance(), -// getATokenInstances(), -// getAllAssetsInstances() -// ]) -// _lendingPoolInstance = instances[0] -// _lendingPoolCoreInstance = instances[1] -// _aTokenInstances = instances[2] -// _tokenInstances = instances[3] -// _daiAddress = _tokenInstances.DAI.address -// _depositorAddress = await getFirstDepositorAddressOnTests() -// _borrowerAddress = await getFirstBorrowerAddressOnTests() - -// _web3 = await getWeb3() -// console.timeEnd('setup-test'); -// }) - -// it("BORROW - Test user cannot borrow using the same currency as collateral", async () => { -// const {aDAI: aDaiInstance} = _aTokenInstances -// const {DAI: daiInstance} = _tokenInstances - -// //mints DAI to depositor -// await daiInstance.mint(await convertToCurrencyDecimals(daiInstance.address, "1000"), { -// from: _depositorAddress, -// }) - -// //mints DAI to borrower -// await daiInstance.mint(await convertToCurrencyDecimals(daiInstance.address, "1000"), { -// from: _borrowerAddress, -// }) - -// //approve protocol to access depositor wallet -// await daiInstance.approve(_lendingPoolCoreInstance.address, APPROVAL_AMOUNT_LENDING_POOL_CORE, { -// from: _depositorAddress, -// }) - -// //approve protocol to access borrower wallet -// await daiInstance.approve(_lendingPoolCoreInstance.address, APPROVAL_AMOUNT_LENDING_POOL_CORE, { -// from: _borrowerAddress, -// }) - -// const amountDAItoDeposit = await convertToCurrencyDecimals(_daiAddress, "1000") - -// //user 1 deposits 1000 DAI -// const txResult = await _lendingPoolInstance.deposit(_daiAddress, amountDAItoDeposit, "0", { -// from: _depositorAddress, -// }) - -// //user 2 deposits 1000 DAI, tries to borrow. Needs to be reverted as you can't borrow at a stable rate with the same collateral as the currency. -// const amountDAIToDepositBorrower = await convertToCurrencyDecimals(_daiAddress, "1000") -// await _lendingPoolInstance.deposit(_daiAddress, amountDAIToDepositBorrower, "0", { -// from: _borrowerAddress, -// }) - -// const data: any = await _lendingPoolInstance.getReserveData(_daiAddress) - -// //user 2 tries to borrow -// const amountDAIToBorrow = await convertToCurrencyDecimals(_daiAddress, "250") - -// //user 2 tries to borrow -// await expectRevert( -// _lendingPoolInstance.borrow(_daiAddress, amountDAIToBorrow, RateMode.Stable, "0", { -// from: _borrowerAddress, -// }), -// "User cannot borrow the selected amount with a stable rate", -// ) -// }) - -// it("BORROW - Test user cannot borrow more than 25% of the liquidity available", async () => { -// const {aDAI: aDaiInstance} = _aTokenInstances -// const {DAI: daiInstance} = _tokenInstances - -// //redeem the DAI previously deposited -// const amountADAIToRedeem = await convertToCurrencyDecimals(aDaiInstance.address, "1000") -// await aDaiInstance.redeem(amountADAIToRedeem, { -// from: _borrowerAddress, -// }) - -// //user 2 deposits 5 ETH tries to borrow. needs to be reverted as you can't borrow more than 25% of the available reserve (250 DAI) -// const amountETHToDeposit = await convertToCurrencyDecimals(ETHEREUM_ADDRESS, "5") -// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, amountETHToDeposit, "0", { -// from: _borrowerAddress, -// value: amountETHToDeposit, -// }) - -// const data: any = await _lendingPoolInstance.getReserveData(_daiAddress) - -// const amountDAIToBorrow = await convertToCurrencyDecimals(_daiAddress, "500") - -// //user 2 tries to borrow -// await expectRevert( -// _lendingPoolInstance.borrow(_daiAddress, amountDAIToBorrow, RateMode.Stable, "0", { -// from: _borrowerAddress, -// }), -// "User is trying to borrow too much liquidity at a stable rate", -// ) -// }) - -// it("BORROW - Test user can still borrow a currency that he previously deposited as a collateral but he transferred/redeemed", async () => { -// const {aDAI: aDaiInstance} = _aTokenInstances -// const {DAI: daiInstance} = _tokenInstances - -// const user = users[2] - -// //user deposits 1000 DAI -// await daiInstance.mint(await convertToCurrencyDecimals(daiInstance.address, "1000"), { -// from: user, -// }) -// await daiInstance.approve(_lendingPoolCoreInstance.address, APPROVAL_AMOUNT_LENDING_POOL_CORE, { -// from: user, -// }) - -// const amountDAIToDeposit = await convertToCurrencyDecimals(daiInstance.address, "1000") -// await _lendingPoolInstance.deposit(daiInstance.address, amountDAIToDeposit, "0", { -// from: user, -// }) - -// //user deposits 5 ETH as collateral -// const amountETHToDeposit = await convertToCurrencyDecimals(ETHEREUM_ADDRESS, "5") -// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, amountETHToDeposit, "0", { -// from: user, -// value: amountETHToDeposit, -// }) - -// //user transfers to another address all the overlying aDAI - -// const aDAIBalance = await aDaiInstance.balanceOf(user) - -// await aDaiInstance.transfer(users[3], aDAIBalance, { -// from: user, -// }) - -// //check the underlying balance is 0 -// const userData: any = await _lendingPoolInstance.getUserReserveData(daiInstance.address, user) - -// expect(userData.currentATokenBalance.toString()).to.be.equal("0") - -// //user tries to borrow the DAI at a stable rate using the ETH as collateral -// const amountDAIToBorrow = await convertToCurrencyDecimals(_daiAddress, "100") - -// //user tries to borrow. No revert expected -// await _lendingPoolInstance.borrow(_daiAddress, amountDAIToBorrow, RateMode.Stable, "0", { -// from: user, -// }) -// }) -// }) diff --git a/test/stable-token.spec.ts b/test/stable-token.spec.ts deleted file mode 100644 index ab588a81..00000000 --- a/test/stable-token.spec.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { expect } from 'chai'; -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { ProtocolErrors } from '../helpers/types'; -import { getStableDebtToken } from '../helpers/contracts-getters'; - -makeSuite('Stable debt token tests', (testEnv: TestEnv) => { - const { CT_CALLER_MUST_BE_LENDING_POOL } = ProtocolErrors; - - it('Tries to invoke mint not being the LendingPool', async () => { - const { deployer, pool, dai, helpersContract } = testEnv; - - const daiStableDebtTokenAddress = (await helpersContract.getReserveTokensAddresses(dai.address)) - .stableDebtTokenAddress; - - const stableDebtContract = await getStableDebtToken(daiStableDebtTokenAddress); - - await expect( - stableDebtContract.mint(deployer.address, deployer.address, '1', '1') - ).to.be.revertedWith(CT_CALLER_MUST_BE_LENDING_POOL); - }); - - it('Tries to invoke burn not being the LendingPool', async () => { - const { deployer, dai, helpersContract } = testEnv; - - const daiStableDebtTokenAddress = (await helpersContract.getReserveTokensAddresses(dai.address)) - .stableDebtTokenAddress; - - const stableDebtContract = await getStableDebtToken(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( - CT_CALLER_MUST_BE_LENDING_POOL - ); - }); -}); diff --git a/test/subgraph-scenarios.spec.ts b/test/subgraph-scenarios.spec.ts deleted file mode 100644 index 27f0b994..00000000 --- a/test/subgraph-scenarios.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { configuration as actionsConfiguration } from './helpers/actions'; -import { configuration as calculationsConfiguration } from './helpers/utils/calculations'; - -import BigNumber from 'bignumber.js'; -import { makeSuite } from './helpers/make-suite'; -import { getReservesConfigByPool } from '../helpers/configuration'; -import { AavePools, iAavePoolAssets, IReserveParams } from '../helpers/types'; -import { executeStory } from './helpers/scenario-engine'; - -makeSuite('Subgraph scenario tests', async (testEnv) => { - let story: any; - let scenario; - before('Initializing configuration', async () => { - const scenario = require(`./helpers/scenarios/borrow-repay-stable`); - story = scenario.stories[0]; - // Sets BigNumber for this suite, instead of globally - BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); - - actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage - - calculationsConfiguration.reservesParams = >( - getReservesConfigByPool(AavePools.proto) - ); - }); - after('Reset', () => { - // Reset BigNumber - BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); - }); - it('deposit-borrow', async () => { - await executeStory(story, testEnv); - }); -}); diff --git a/test/uniswapAdapters.base.spec.ts b/test/uniswapAdapters.base.spec.ts deleted file mode 100644 index 80f76725..00000000 --- a/test/uniswapAdapters.base.spec.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { convertToCurrencyDecimals } from '../helpers/contracts-helpers'; -import { getMockUniswapRouter } from '../helpers/contracts-getters'; -import { MockUniswapV2Router02 } from '../types/MockUniswapV2Router02'; -import BigNumber from 'bignumber.js'; -import { evmRevert, evmSnapshot } from '../helpers/misc-utils'; -import { ethers } from 'ethers'; -import { USD_ADDRESS } from '../helpers/constants'; -const { parseEther } = ethers.utils; - -const { expect } = require('chai'); - -makeSuite('Uniswap adapters', (testEnv: TestEnv) => { - let mockUniswapRouter: MockUniswapV2Router02; - let evmSnapshotId: string; - - before(async () => { - mockUniswapRouter = await getMockUniswapRouter(); - }); - - beforeEach(async () => { - evmSnapshotId = await evmSnapshot(); - }); - - afterEach(async () => { - await evmRevert(evmSnapshotId); - }); - - describe('BaseUniswapAdapter', () => { - describe('getAmountsOut', () => { - it('should return the estimated amountOut and prices for the asset swap', async () => { - const { weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv; - - const amountIn = parseEther('1'); - const flashloanPremium = amountIn.mul(9).div(10000); - const amountToSwap = amountIn.sub(flashloanPremium); - - const wethPrice = await oracle.getAssetPrice(weth.address); - const daiPrice = await oracle.getAssetPrice(dai.address); - const usdPrice = await oracle.getAssetPrice(USD_ADDRESS); - - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountToSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - const outPerInPrice = amountToSwap - .mul(parseEther('1')) - .mul(parseEther('1')) - .div(expectedDaiAmount.mul(parseEther('1'))); - const ethUsdValue = amountIn - .mul(wethPrice) - .div(parseEther('1')) - .mul(usdPrice) - .div(parseEther('1')); - const daiUsdValue = expectedDaiAmount - .mul(daiPrice) - .div(parseEther('1')) - .mul(usdPrice) - .div(parseEther('1')); - - await mockUniswapRouter.setAmountOut( - amountToSwap, - weth.address, - dai.address, - expectedDaiAmount - ); - - const result = await uniswapLiquiditySwapAdapter.getAmountsOut( - amountIn, - weth.address, - dai.address - ); - - expect(result['0']).to.be.eq(expectedDaiAmount); - expect(result['1']).to.be.eq(outPerInPrice); - expect(result['2']).to.be.eq(ethUsdValue); - expect(result['3']).to.be.eq(daiUsdValue); - }); - it('should work correctly with different decimals', async () => { - const { aave, usdc, uniswapLiquiditySwapAdapter, oracle } = testEnv; - - const amountIn = parseEther('10'); - const flashloanPremium = amountIn.mul(9).div(10000); - const amountToSwap = amountIn.sub(flashloanPremium); - - const aavePrice = await oracle.getAssetPrice(aave.address); - const usdcPrice = await oracle.getAssetPrice(usdc.address); - const usdPrice = await oracle.getAssetPrice(USD_ADDRESS); - - const expectedUSDCAmount = await convertToCurrencyDecimals( - usdc.address, - new BigNumber(amountToSwap.toString()).div(usdcPrice.toString()).toFixed(0) - ); - - const outPerInPrice = amountToSwap - .mul(parseEther('1')) - .mul('1000000') // usdc 6 decimals - .div(expectedUSDCAmount.mul(parseEther('1'))); - - const aaveUsdValue = amountIn - .mul(aavePrice) - .div(parseEther('1')) - .mul(usdPrice) - .div(parseEther('1')); - - const usdcUsdValue = expectedUSDCAmount - .mul(usdcPrice) - .div('1000000') // usdc 6 decimals - .mul(usdPrice) - .div(parseEther('1')); - - await mockUniswapRouter.setAmountOut( - amountToSwap, - aave.address, - usdc.address, - expectedUSDCAmount - ); - - const result = await uniswapLiquiditySwapAdapter.getAmountsOut( - amountIn, - aave.address, - usdc.address - ); - - expect(result['0']).to.be.eq(expectedUSDCAmount); - expect(result['1']).to.be.eq(outPerInPrice); - expect(result['2']).to.be.eq(aaveUsdValue); - expect(result['3']).to.be.eq(usdcUsdValue); - }); - }); - - describe('getAmountsIn', () => { - it('should return the estimated required amountIn for the asset swap', async () => { - const { weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv; - - const amountIn = parseEther('1'); - const flashloanPremium = amountIn.mul(9).div(10000); - const amountToSwap = amountIn.add(flashloanPremium); - - const wethPrice = await oracle.getAssetPrice(weth.address); - const daiPrice = await oracle.getAssetPrice(dai.address); - const usdPrice = await oracle.getAssetPrice(USD_ADDRESS); - - const amountOut = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountIn.toString()).div(daiPrice.toString()).toFixed(0) - ); - - const inPerOutPrice = amountOut - .mul(parseEther('1')) - .mul(parseEther('1')) - .div(amountToSwap.mul(parseEther('1'))); - - const ethUsdValue = amountToSwap - .mul(wethPrice) - .div(parseEther('1')) - .mul(usdPrice) - .div(parseEther('1')); - const daiUsdValue = amountOut - .mul(daiPrice) - .div(parseEther('1')) - .mul(usdPrice) - .div(parseEther('1')); - - await mockUniswapRouter.setAmountIn(amountOut, weth.address, dai.address, amountIn); - - const result = await uniswapLiquiditySwapAdapter.getAmountsIn( - amountOut, - weth.address, - dai.address - ); - - expect(result['0']).to.be.eq(amountToSwap); - expect(result['1']).to.be.eq(inPerOutPrice); - expect(result['2']).to.be.eq(ethUsdValue); - expect(result['3']).to.be.eq(daiUsdValue); - }); - it('should work correctly with different decimals', async () => { - const { aave, usdc, uniswapLiquiditySwapAdapter, oracle } = testEnv; - - const amountIn = parseEther('10'); - const flashloanPremium = amountIn.mul(9).div(10000); - const amountToSwap = amountIn.add(flashloanPremium); - - const aavePrice = await oracle.getAssetPrice(aave.address); - const usdcPrice = await oracle.getAssetPrice(usdc.address); - const usdPrice = await oracle.getAssetPrice(USD_ADDRESS); - - const amountOut = await convertToCurrencyDecimals( - usdc.address, - new BigNumber(amountToSwap.toString()).div(usdcPrice.toString()).toFixed(0) - ); - - const inPerOutPrice = amountOut - .mul(parseEther('1')) - .mul(parseEther('1')) - .div(amountToSwap.mul('1000000')); // usdc 6 decimals - - const aaveUsdValue = amountToSwap - .mul(aavePrice) - .div(parseEther('1')) - .mul(usdPrice) - .div(parseEther('1')); - - const usdcUsdValue = amountOut - .mul(usdcPrice) - .div('1000000') // usdc 6 decimals - .mul(usdPrice) - .div(parseEther('1')); - - await mockUniswapRouter.setAmountIn(amountOut, aave.address, usdc.address, amountIn); - - const result = await uniswapLiquiditySwapAdapter.getAmountsIn( - amountOut, - aave.address, - usdc.address - ); - - expect(result['0']).to.be.eq(amountToSwap); - expect(result['1']).to.be.eq(inPerOutPrice); - expect(result['2']).to.be.eq(aaveUsdValue); - expect(result['3']).to.be.eq(usdcUsdValue); - }); - }); - }); -}); diff --git a/test/uniswapAdapters.flashLiquidation.spec.ts b/test/uniswapAdapters.flashLiquidation.spec.ts deleted file mode 100644 index 063c6930..00000000 --- a/test/uniswapAdapters.flashLiquidation.spec.ts +++ /dev/null @@ -1,850 +0,0 @@ -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { - convertToCurrencyDecimals, - buildFlashLiquidationAdapterParams, -} from '../helpers/contracts-helpers'; -import { getMockUniswapRouter } from '../helpers/contracts-getters'; -import { deployFlashLiquidationAdapter } from '../helpers/contracts-deployments'; -import { MockUniswapV2Router02 } from '../types/MockUniswapV2Router02'; -import BigNumber from 'bignumber.js'; -import { DRE, evmRevert, evmSnapshot, increaseTime, waitForTx } from '../helpers/misc-utils'; -import { ethers } from 'ethers'; -import { ProtocolErrors, RateMode } from '../helpers/types'; -import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, oneEther } from '../helpers/constants'; -import { getUserData } from './helpers/utils/helpers'; -import { calcExpectedStableDebtTokenBalance } from './helpers/utils/calculations'; -const { expect } = require('chai'); - -makeSuite('Uniswap adapters', (testEnv: TestEnv) => { - let mockUniswapRouter: MockUniswapV2Router02; - let evmSnapshotId: string; - const { INVALID_HF, LP_LIQUIDATION_CALL_FAILED } = ProtocolErrors; - - before(async () => { - mockUniswapRouter = await getMockUniswapRouter(); - }); - - const depositAndHFBelowOne = async () => { - const { dai, weth, users, pool, oracle } = testEnv; - const depositor = users[0]; - const borrower = users[1]; - - //mints DAI to depositor - await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); - - //approve protocol to access depositor wallet - await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - //user 1 deposits 1000 DAI - const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await pool - .connect(depositor.signer) - .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); - //user 2 deposits 1 ETH - const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); - - //mints WETH to borrower - await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); - - //approve protocol to access the borrower wallet - await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - await pool - .connect(borrower.signer) - .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); - - //user 2 borrows - - const userGlobalDataBefore = await pool.getUserAccountData(borrower.address); - const daiPrice = await oracle.getAssetPrice(dai.address); - - const amountDAIToBorrow = await convertToCurrencyDecimals( - dai.address, - new BigNumber(userGlobalDataBefore.availableBorrowsETH.toString()) - .div(daiPrice.toString()) - .multipliedBy(0.95) - .toFixed(0) - ); - - await pool - .connect(borrower.signer) - .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address); - - const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); - - expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.equal( - '8250', - INVALID_HF - ); - - await oracle.setAssetPrice( - dai.address, - new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0) - ); - - const userGlobalData = await pool.getUserAccountData(borrower.address); - - expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( - oneEther.toFixed(0), - INVALID_HF - ); - }; - - const depositSameAssetAndHFBelowOne = async () => { - const { dai, weth, users, pool, oracle } = testEnv; - const depositor = users[0]; - const borrower = users[1]; - - //mints DAI to depositor - await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); - - //approve protocol to access depositor wallet - await dai.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - //user 1 deposits 1000 DAI - const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await pool - .connect(depositor.signer) - .deposit(dai.address, amountDAItoDeposit, depositor.address, '0'); - //user 2 deposits 1 ETH - const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); - - //mints WETH to borrower - await weth.connect(borrower.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); - - //approve protocol to access the borrower wallet - await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - await pool - .connect(borrower.signer) - .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); - - //user 2 borrows - - const userGlobalDataBefore = await pool.getUserAccountData(borrower.address); - const daiPrice = await oracle.getAssetPrice(dai.address); - - const amountDAIToBorrow = await convertToCurrencyDecimals( - dai.address, - new BigNumber(userGlobalDataBefore.availableBorrowsETH.toString()) - .div(daiPrice.toString()) - .multipliedBy(0.8) - .toFixed(0) - ); - await waitForTx( - await pool - .connect(borrower.signer) - .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address) - ); - - const userGlobalDataBefore2 = await pool.getUserAccountData(borrower.address); - - const amountWETHToBorrow = new BigNumber(userGlobalDataBefore2.availableBorrowsETH.toString()) - .multipliedBy(0.8) - .toFixed(0); - - await pool - .connect(borrower.signer) - .borrow(weth.address, amountWETHToBorrow, RateMode.Variable, '0', borrower.address); - - const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); - - expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.equal( - '8250', - INVALID_HF - ); - - await oracle.setAssetPrice( - dai.address, - new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0) - ); - - const userGlobalData = await pool.getUserAccountData(borrower.address); - - expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt( - oneEther.toFixed(0), - INVALID_HF - ); - }; - - beforeEach(async () => { - evmSnapshotId = await evmSnapshot(); - }); - - afterEach(async () => { - await evmRevert(evmSnapshotId); - }); - - describe('Flash Liquidation Adapter', () => { - before('Before LendingPool liquidation: set config', () => { - BigNumber.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN }); - }); - - after('After LendingPool liquidation: reset config', () => { - BigNumber.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP }); - }); - - describe('constructor', () => { - it('should deploy with correct parameters', async () => { - const { addressesProvider, weth } = testEnv; - await deployFlashLiquidationAdapter([ - addressesProvider.address, - mockUniswapRouter.address, - weth.address, - ]); - }); - - it('should revert if not valid addresses provider', async () => { - const { weth } = testEnv; - expect( - deployFlashLiquidationAdapter([ - mockUniswapRouter.address, - mockUniswapRouter.address, - weth.address, - ]) - ).to.be.reverted; - }); - }); - - describe('executeOperation: succesfully liquidateCall and swap via Flash Loan with profits', () => { - it('Liquidates the borrow with profit', async () => { - await depositAndHFBelowOne(); - await increaseTime(100); - - const { - dai, - weth, - users, - pool, - oracle, - helpersContract, - flashLiquidationAdapter, - } = testEnv; - - const liquidator = users[3]; - const borrower = users[1]; - const expectedSwap = ethers.utils.parseEther('0.4'); - - const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); - - // Set how much ETH will be sold and swapped for DAI at Uniswap mock - await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); - - const collateralPrice = await oracle.getAssetPrice(weth.address); - const principalPrice = await oracle.getAssetPrice(dai.address); - const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); - const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); - const userReserveDataBefore = await getUserData( - pool, - helpersContract, - dai.address, - borrower.address - ); - - const collateralDecimals = ( - await helpersContract.getReserveConfigurationData(weth.address) - ).decimals.toString(); - const principalDecimals = ( - await helpersContract.getReserveConfigurationData(dai.address) - ).decimals.toString(); - const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); - - const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) - .times(new BigNumber(amountToLiquidate).times(105)) - .times(new BigNumber(10).pow(collateralDecimals)) - .div( - new BigNumber(collateralPrice.toString()).times( - new BigNumber(10).pow(principalDecimals) - ) - ) - .div(100) - .decimalPlaces(0, BigNumber.ROUND_DOWN); - - const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) - .multipliedBy(1.0009) - .toFixed(0); - - const expectedProfit = ethers.BigNumber.from(expectedCollateralLiquidated.toString()).sub( - expectedSwap - ); - - const params = buildFlashLiquidationAdapterParams( - weth.address, - dai.address, - borrower.address, - amountToLiquidate, - false - ); - const tx = await pool - .connect(liquidator.signer) - .flashLoan( - flashLiquidationAdapter.address, - [dai.address], - [amountToLiquidate], - [0], - borrower.address, - params, - 0 - ); - - // Expect Swapped event - await expect(Promise.resolve(tx)).to.emit(flashLiquidationAdapter, 'Swapped'); - - // Expect LiquidationCall event - await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); - - const userReserveDataAfter = await getUserData( - pool, - helpersContract, - dai.address, - borrower.address - ); - const liquidatorWethBalanceAfter = await weth.balanceOf(liquidator.address); - - const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); - const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); - - if (!tx.blockNumber) { - expect(false, 'Invalid block number'); - return; - } - const txTimestamp = new BigNumber( - (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp - ); - - const stableDebtBeforeTx = calcExpectedStableDebtTokenBalance( - userReserveDataBefore.principalStableDebt, - userReserveDataBefore.stableBorrowRate, - userReserveDataBefore.stableRateLastUpdated, - txTimestamp - ); - - const collateralAssetContractBalance = await weth.balanceOf( - flashLiquidationAdapter.address - ); - const borrowAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); - - expect(collateralAssetContractBalance).to.be.equal( - '0', - 'Contract address should not keep any balance.' - ); - expect(borrowAssetContractBalance).to.be.equal( - '0', - 'Contract address should not keep any balance.' - ); - - expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( - stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), - 'Invalid user debt after liquidation' - ); - - //the liquidity index of the principal reserve needs to be bigger than the index before - expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( - daiReserveDataBefore.liquidityIndex.toString(), - 'Invalid liquidity index' - ); - - //the principal APY after a liquidation needs to be lower than the APY before - expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( - daiReserveDataBefore.liquidityRate.toString(), - 'Invalid liquidity APY' - ); - - expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(daiReserveDataBefore.availableLiquidity.toString()) - .plus(flashLoanDebt) - .toFixed(0), - 'Invalid principal available liquidity' - ); - - expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) - .minus(expectedCollateralLiquidated) - .toFixed(0), - 'Invalid collateral available liquidity' - ); - - // Profit after flash loan liquidation - expect(liquidatorWethBalanceAfter).to.be.equal( - liquidatorWethBalanceBefore.add(expectedProfit), - 'Invalid expected WETH profit' - ); - }); - }); - - describe('executeOperation: succesfully liquidateCall with same asset via Flash Loan, but no swap needed', () => { - it('Liquidates the borrow with profit', async () => { - await depositSameAssetAndHFBelowOne(); - await increaseTime(100); - - const { weth, users, pool, oracle, helpersContract, flashLiquidationAdapter } = testEnv; - - const liquidator = users[3]; - const borrower = users[1]; - - const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); - - const assetPrice = await oracle.getAssetPrice(weth.address); - const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); - const userReserveDataBefore = await getUserData( - pool, - helpersContract, - weth.address, - borrower.address - ); - - const assetDecimals = ( - await helpersContract.getReserveConfigurationData(weth.address) - ).decimals.toString(); - const amountToLiquidate = userReserveDataBefore.currentVariableDebt.div(2).toFixed(0); - - const expectedCollateralLiquidated = new BigNumber(assetPrice.toString()) - .times(new BigNumber(amountToLiquidate).times(105)) - .times(new BigNumber(10).pow(assetDecimals)) - .div(new BigNumber(assetPrice.toString()).times(new BigNumber(10).pow(assetDecimals))) - .div(100) - .decimalPlaces(0, BigNumber.ROUND_DOWN); - - const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) - .multipliedBy(1.0009) - .toFixed(0); - - const params = buildFlashLiquidationAdapterParams( - weth.address, - weth.address, - borrower.address, - amountToLiquidate, - false - ); - const tx = await pool - .connect(liquidator.signer) - .flashLoan( - flashLiquidationAdapter.address, - [weth.address], - [amountToLiquidate], - [0], - borrower.address, - params, - 0 - ); - - // Dont expect Swapped event due is same asset - await expect(Promise.resolve(tx)).to.not.emit(flashLiquidationAdapter, 'Swapped'); - - // Expect LiquidationCall event - await expect(Promise.resolve(tx)) - .to.emit(pool, 'LiquidationCall') - .withArgs( - weth.address, - weth.address, - borrower.address, - amountToLiquidate.toString(), - expectedCollateralLiquidated.toString(), - flashLiquidationAdapter.address, - false - ); - - const borrowAssetContractBalance = await weth.balanceOf(flashLiquidationAdapter.address); - - expect(borrowAssetContractBalance).to.be.equal( - '0', - 'Contract address should not keep any balance.' - ); - }); - }); - - describe('executeOperation: succesfully liquidateCall and swap via Flash Loan without profits', () => { - it('Liquidates the borrow', async () => { - await depositAndHFBelowOne(); - await increaseTime(100); - - const { - dai, - weth, - users, - pool, - oracle, - helpersContract, - flashLiquidationAdapter, - } = testEnv; - - const liquidator = users[3]; - const borrower = users[1]; - const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); - - const collateralPrice = await oracle.getAssetPrice(weth.address); - const principalPrice = await oracle.getAssetPrice(dai.address); - const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); - const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); - const userReserveDataBefore = await getUserData( - pool, - helpersContract, - dai.address, - borrower.address - ); - - const collateralDecimals = ( - await helpersContract.getReserveConfigurationData(weth.address) - ).decimals.toString(); - const principalDecimals = ( - await helpersContract.getReserveConfigurationData(dai.address) - ).decimals.toString(); - const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); - - const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) - .times(new BigNumber(amountToLiquidate).times(105)) - .times(new BigNumber(10).pow(collateralDecimals)) - .div( - new BigNumber(collateralPrice.toString()).times( - new BigNumber(10).pow(principalDecimals) - ) - ) - .div(100) - .decimalPlaces(0, BigNumber.ROUND_DOWN); - - const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) - .multipliedBy(1.0009) - .toFixed(0); - - // Set how much ETH will be sold and swapped for DAI at Uniswap mock - await ( - await mockUniswapRouter.setAmountToSwap( - weth.address, - expectedCollateralLiquidated.toString() - ) - ).wait(); - - const params = buildFlashLiquidationAdapterParams( - weth.address, - dai.address, - borrower.address, - amountToLiquidate, - false - ); - const tx = await pool - .connect(liquidator.signer) - .flashLoan( - flashLiquidationAdapter.address, - [dai.address], - [flashLoanDebt], - [0], - borrower.address, - params, - 0 - ); - - // Expect Swapped event - await expect(Promise.resolve(tx)).to.emit(flashLiquidationAdapter, 'Swapped'); - - // Expect LiquidationCall event - await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); - - const userReserveDataAfter = await getUserData( - pool, - helpersContract, - dai.address, - borrower.address - ); - const liquidatorWethBalanceAfter = await weth.balanceOf(liquidator.address); - - const daiReserveDataAfter = await helpersContract.getReserveData(dai.address); - const ethReserveDataAfter = await helpersContract.getReserveData(weth.address); - - if (!tx.blockNumber) { - expect(false, 'Invalid block number'); - return; - } - const txTimestamp = new BigNumber( - (await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp - ); - - const stableDebtBeforeTx = calcExpectedStableDebtTokenBalance( - userReserveDataBefore.principalStableDebt, - userReserveDataBefore.stableBorrowRate, - userReserveDataBefore.stableRateLastUpdated, - txTimestamp - ); - - const collateralAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); - const borrowAssetContractBalance = await weth.balanceOf(flashLiquidationAdapter.address); - - expect(collateralAssetContractBalance).to.be.equal( - '0', - 'Contract address should not keep any balance.' - ); - expect(borrowAssetContractBalance).to.be.equal( - '0', - 'Contract address should not keep any balance.' - ); - expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual( - stableDebtBeforeTx.minus(amountToLiquidate).toFixed(0), - 'Invalid user debt after liquidation' - ); - - //the liquidity index of the principal reserve needs to be bigger than the index before - expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gte( - daiReserveDataBefore.liquidityIndex.toString(), - 'Invalid liquidity index' - ); - - //the principal APY after a liquidation needs to be lower than the APY before - expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( - daiReserveDataBefore.liquidityRate.toString(), - 'Invalid liquidity APY' - ); - - expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( - new BigNumber(ethReserveDataBefore.availableLiquidity.toString()) - .minus(expectedCollateralLiquidated) - .toFixed(0), - 'Invalid collateral available liquidity' - ); - - // Net Profit == 0 after flash loan liquidation - expect(liquidatorWethBalanceAfter).to.be.equal( - liquidatorWethBalanceBefore, - 'Invalid expected WETH profit' - ); - }); - }); - - describe('executeOperation: succesfully liquidateCall all available debt and swap via Flash Loan ', () => { - it('Liquidates the borrow', async () => { - await depositAndHFBelowOne(); - await increaseTime(100); - - const { - dai, - weth, - users, - pool, - oracle, - helpersContract, - flashLiquidationAdapter, - } = testEnv; - - const liquidator = users[3]; - const borrower = users[1]; - const liquidatorWethBalanceBefore = await weth.balanceOf(liquidator.address); - - const collateralPrice = await oracle.getAssetPrice(weth.address); - const principalPrice = await oracle.getAssetPrice(dai.address); - const daiReserveDataBefore = await helpersContract.getReserveData(dai.address); - const ethReserveDataBefore = await helpersContract.getReserveData(weth.address); - const userReserveDataBefore = await getUserData( - pool, - helpersContract, - dai.address, - borrower.address - ); - - const collateralDecimals = ( - await helpersContract.getReserveConfigurationData(weth.address) - ).decimals.toString(); - const principalDecimals = ( - await helpersContract.getReserveConfigurationData(dai.address) - ).decimals.toString(); - const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); - const extraAmount = new BigNumber(amountToLiquidate).times('1.15').toFixed(0); - - const expectedCollateralLiquidated = new BigNumber(principalPrice.toString()) - .times(new BigNumber(amountToLiquidate).times(105)) - .times(new BigNumber(10).pow(collateralDecimals)) - .div( - new BigNumber(collateralPrice.toString()).times( - new BigNumber(10).pow(principalDecimals) - ) - ) - .div(100) - .decimalPlaces(0, BigNumber.ROUND_DOWN); - - const flashLoanDebt = new BigNumber(amountToLiquidate.toString()) - .multipliedBy(1.0009) - .toFixed(0); - - // Set how much ETH will be sold and swapped for DAI at Uniswap mock - await ( - await mockUniswapRouter.setAmountToSwap( - weth.address, - expectedCollateralLiquidated.toString() - ) - ).wait(); - - const params = buildFlashLiquidationAdapterParams( - weth.address, - dai.address, - borrower.address, - MAX_UINT_AMOUNT, - false - ); - const tx = await pool - .connect(liquidator.signer) - .flashLoan( - flashLiquidationAdapter.address, - [dai.address], - [extraAmount], - [0], - borrower.address, - params, - 0 - ); - - // Expect Swapped event - await expect(Promise.resolve(tx)).to.emit(flashLiquidationAdapter, 'Swapped'); - - // Expect LiquidationCall event - await expect(Promise.resolve(tx)).to.emit(pool, 'LiquidationCall'); - - const collateralAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); - const borrowAssetContractBalance = await dai.balanceOf(flashLiquidationAdapter.address); - - expect(collateralAssetContractBalance).to.be.equal( - '0', - 'Contract address should not keep any balance.' - ); - expect(borrowAssetContractBalance).to.be.equal( - '0', - 'Contract address should not keep any balance.' - ); - }); - }); - - describe('executeOperation: invalid params', async () => { - it('Revert if debt asset is different than requested flash loan token', async () => { - await depositAndHFBelowOne(); - - const { dai, weth, users, pool, helpersContract, flashLiquidationAdapter } = testEnv; - - const liquidator = users[3]; - const borrower = users[1]; - const expectedSwap = ethers.utils.parseEther('0.4'); - - // Set how much ETH will be sold and swapped for DAI at Uniswap mock - await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); - - const userReserveDataBefore = await getUserData( - pool, - helpersContract, - dai.address, - borrower.address - ); - - const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2).toFixed(0); - - // Wrong debt asset - const params = buildFlashLiquidationAdapterParams( - weth.address, - weth.address, // intentionally bad - borrower.address, - amountToLiquidate, - false - ); - await expect( - pool - .connect(liquidator.signer) - .flashLoan( - flashLiquidationAdapter.address, - [dai.address], - [amountToLiquidate], - [0], - borrower.address, - params, - 0 - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - }); - - it('Revert if debt asset amount to liquidate is greater than requested flash loan', async () => { - await depositAndHFBelowOne(); - - const { dai, weth, users, pool, helpersContract, flashLiquidationAdapter } = testEnv; - - const liquidator = users[3]; - const borrower = users[1]; - const expectedSwap = ethers.utils.parseEther('0.4'); - - // Set how much ETH will be sold and swapped for DAI at Uniswap mock - await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); - - const userReserveDataBefore = await getUserData( - pool, - helpersContract, - dai.address, - borrower.address - ); - - const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2); - - // Correct params - const params = buildFlashLiquidationAdapterParams( - weth.address, - dai.address, - borrower.address, - amountToLiquidate.toString(), - false - ); - // Bad flash loan params: requested DAI amount below amountToLiquidate - await expect( - pool - .connect(liquidator.signer) - .flashLoan( - flashLiquidationAdapter.address, - [dai.address], - [amountToLiquidate.div(2).toString()], - [0], - borrower.address, - params, - 0 - ) - ).to.be.revertedWith(LP_LIQUIDATION_CALL_FAILED); - }); - - it('Revert if requested multiple assets', async () => { - await depositAndHFBelowOne(); - - const { dai, weth, users, pool, helpersContract, flashLiquidationAdapter } = testEnv; - - const liquidator = users[3]; - const borrower = users[1]; - const expectedSwap = ethers.utils.parseEther('0.4'); - - // Set how much ETH will be sold and swapped for DAI at Uniswap mock - await (await mockUniswapRouter.setAmountToSwap(weth.address, expectedSwap)).wait(); - - const userReserveDataBefore = await getUserData( - pool, - helpersContract, - dai.address, - borrower.address - ); - - const amountToLiquidate = userReserveDataBefore.currentStableDebt.div(2); - - // Correct params - const params = buildFlashLiquidationAdapterParams( - weth.address, - dai.address, - borrower.address, - amountToLiquidate.toString(), - false - ); - // Bad flash loan params: requested multiple assets - await expect( - pool - .connect(liquidator.signer) - .flashLoan( - flashLiquidationAdapter.address, - [dai.address, weth.address], - [10, 10], - [0], - borrower.address, - params, - 0 - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - }); - }); - }); -}); diff --git a/test/uniswapAdapters.liquiditySwap.spec.ts b/test/uniswapAdapters.liquiditySwap.spec.ts deleted file mode 100644 index 1e30b2b3..00000000 --- a/test/uniswapAdapters.liquiditySwap.spec.ts +++ /dev/null @@ -1,1854 +0,0 @@ -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { - convertToCurrencyDecimals, - getContract, - buildPermitParams, - getSignatureFromTypedData, - buildLiquiditySwapParams, -} from '../helpers/contracts-helpers'; -import { getMockUniswapRouter } from '../helpers/contracts-getters'; -import { deployUniswapLiquiditySwapAdapter } from '../helpers/contracts-deployments'; -import { MockUniswapV2Router02 } from '../types/MockUniswapV2Router02'; -import { Zero } from '@ethersproject/constants'; -import BigNumber from 'bignumber.js'; -import { DRE, evmRevert, evmSnapshot } from '../helpers/misc-utils'; -import { ethers } from 'ethers'; -import { eContractid } from '../helpers/types'; -import { AToken } from '../types/AToken'; -import { BUIDLEREVM_CHAINID } from '../helpers/buidler-constants'; -import { MAX_UINT_AMOUNT } from '../helpers/constants'; -const { parseEther } = ethers.utils; - -const { expect } = require('chai'); - -makeSuite('Uniswap adapters', (testEnv: TestEnv) => { - let mockUniswapRouter: MockUniswapV2Router02; - let evmSnapshotId: string; - - before(async () => { - mockUniswapRouter = await getMockUniswapRouter(); - }); - - beforeEach(async () => { - evmSnapshotId = await evmSnapshot(); - }); - - afterEach(async () => { - await evmRevert(evmSnapshotId); - }); - - describe('UniswapLiquiditySwapAdapter', () => { - describe('constructor', () => { - it('should deploy with correct parameters', async () => { - const { addressesProvider, weth } = testEnv; - await deployUniswapLiquiditySwapAdapter([ - addressesProvider.address, - mockUniswapRouter.address, - weth.address, - ]); - }); - - it('should revert if not valid addresses provider', async () => { - const { weth } = testEnv; - expect( - deployUniswapLiquiditySwapAdapter([ - mockUniswapRouter.address, - mockUniswapRouter.address, - weth.address, - ]) - ).to.be.reverted; - }); - }); - - describe('executeOperation', () => { - beforeEach(async () => { - const { users, weth, dai, usdc, pool, deployer } = testEnv; - const userAddress = users[0].address; - - // Provide liquidity - await dai.mint(parseEther('20000')); - await dai.approve(pool.address, parseEther('20000')); - await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); - - const usdcAmount = await convertToCurrencyDecimals(usdc.address, '10'); - await usdc.mint(usdcAmount); - await usdc.approve(pool.address, usdcAmount); - await pool.deposit(usdc.address, usdcAmount, deployer.address, 0); - - // Make a deposit for user - await weth.mint(parseEther('100')); - await weth.approve(pool.address, parseEther('100')); - await pool.deposit(weth.address, parseEther('100'), userAddress, 0); - }); - - it('should correctly swap tokens and deposit the out tokens in the pool', async () => { - const { - users, - weth, - oracle, - dai, - aDai, - aWETH, - pool, - uniswapLiquiditySwapAdapter, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); - - // User will swap liquidity 10 aEth to aDai - const liquidityToSwap = parseEther('10'); - await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - // Subtract the FL fee from the amount to be swapped 0,09% - const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); - - const params = buildLiquiditySwapParams( - [dai.address], - [expectedDaiAmount], - [0], - [0], - [0], - [0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params, - 0 - ) - ) - .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') - .withArgs(weth.address, dai.address, flashloanAmount.toString(), expectedDaiAmount); - - const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const userADaiBalance = await aDai.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(userADaiBalance).to.be.eq(expectedDaiAmount); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); - }); - - it('should correctly swap and deposit multiple tokens', async () => { - const { - users, - weth, - oracle, - dai, - aDai, - aWETH, - usdc, - pool, - uniswapLiquiditySwapAdapter, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmountForEth = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); - const usdcPrice = await oracle.getAssetPrice(usdc.address); - - const collateralDecimals = (await usdc.decimals()).toString(); - const principalDecimals = (await dai.decimals()).toString(); - - const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountUSDCtoSwap.toString()) - .times( - new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) - ) - .div( - new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) - ) - .toFixed(0) - ); - - // Make a deposit for user - await usdc.connect(user).mint(amountUSDCtoSwap); - await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); - await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); - - const aUsdcData = await pool.getReserveData(usdc.address); - const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); - await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); - - await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountWETHtoSwap); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - await aUsdc.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountUSDCtoSwap); - const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); - - // Subtract the FL fee from the amount to be swapped 0,09% - const wethFlashloanAmount = new BigNumber(amountWETHtoSwap.toString()) - .div(1.0009) - .toFixed(0); - const usdcFlashloanAmount = new BigNumber(amountUSDCtoSwap.toString()) - .div(1.0009) - .toFixed(0); - - const params = buildLiquiditySwapParams( - [dai.address, dai.address], - [expectedDaiAmountForEth, expectedDaiAmountForUsdc], - [0, 0], - [0, 0], - [0, 0], - [0, 0], - [ - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - ], - [ - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - ], - [false, false] - ); - - await pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address, usdc.address], - [wethFlashloanAmount.toString(), usdcFlashloanAmount.toString()], - [0, 0], - userAddress, - params, - 0 - ); - - const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const userADaiBalance = await aDai.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const userAUsdcBalance = await aUsdc.balanceOf(userAddress); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); - expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); - expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); - }); - - it('should correctly swap and deposit multiple tokens using permit', async () => { - const { - users, - weth, - oracle, - dai, - aDai, - aWETH, - usdc, - pool, - uniswapLiquiditySwapAdapter, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const deadline = MAX_UINT_AMOUNT; - - const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmountForEth = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); - const usdcPrice = await oracle.getAssetPrice(usdc.address); - - const collateralDecimals = (await usdc.decimals()).toString(); - const principalDecimals = (await dai.decimals()).toString(); - - const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountUSDCtoSwap.toString()) - .times( - new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) - ) - .div( - new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) - ) - .toFixed(0) - ); - - // Make a deposit for user - await usdc.connect(user).mint(amountUSDCtoSwap); - await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); - await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); - - const aUsdcData = await pool.getReserveData(usdc.address); - const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); - await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); - - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); - - const wethFlashloanAmount = new BigNumber(amountWETHtoSwap.toString()) - .div(1.0009) - .toFixed(0); - - const usdcFlashloanAmount = new BigNumber(amountUSDCtoSwap.toString()) - .div(1.0009) - .toFixed(0); - - const aWethNonce = (await aWETH._nonces(userAddress)).toNumber(); - const aWethMsgParams = buildPermitParams( - chainId, - aWETH.address, - '1', - await aWETH.name(), - userAddress, - uniswapLiquiditySwapAdapter.address, - aWethNonce, - deadline, - amountWETHtoSwap.toString() - ); - const { v: aWETHv, r: aWETHr, s: aWETHs } = getSignatureFromTypedData( - ownerPrivateKey, - aWethMsgParams - ); - - const aUsdcNonce = (await aUsdc._nonces(userAddress)).toNumber(); - const aUsdcMsgParams = buildPermitParams( - chainId, - aUsdc.address, - '1', - await aUsdc.name(), - userAddress, - uniswapLiquiditySwapAdapter.address, - aUsdcNonce, - deadline, - amountUSDCtoSwap.toString() - ); - const { v: aUsdcv, r: aUsdcr, s: aUsdcs } = getSignatureFromTypedData( - ownerPrivateKey, - aUsdcMsgParams - ); - const params = buildLiquiditySwapParams( - [dai.address, dai.address], - [expectedDaiAmountForEth, expectedDaiAmountForUsdc], - [0, 0], - [amountWETHtoSwap, amountUSDCtoSwap], - [deadline, deadline], - [aWETHv, aUsdcv], - [aWETHr, aUsdcr], - [aWETHs, aUsdcs], - [false, false] - ); - - await pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address, usdc.address], - [wethFlashloanAmount.toString(), usdcFlashloanAmount.toString()], - [0, 0], - userAddress, - params, - 0 - ); - - const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const userADaiBalance = await aDai.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const userAUsdcBalance = await aUsdc.balanceOf(userAddress); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); - expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); - expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); - }); - - it('should correctly swap tokens with permit', async () => { - const { - users, - weth, - oracle, - dai, - aDai, - aWETH, - pool, - uniswapLiquiditySwapAdapter, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); - - // User will swap liquidity 10 aEth to aDai - const liquidityToSwap = parseEther('10'); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - // Subtract the FL fee from the amount to be swapped 0,09% - const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const deadline = MAX_UINT_AMOUNT; - const nonce = (await aWETH._nonces(userAddress)).toNumber(); - const msgParams = buildPermitParams( - chainId, - aWETH.address, - '1', - await aWETH.name(), - userAddress, - uniswapLiquiditySwapAdapter.address, - nonce, - deadline, - liquidityToSwap.toString() - ); - - const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); - - const params = buildLiquiditySwapParams( - [dai.address], - [expectedDaiAmount], - [0], - [liquidityToSwap], - [deadline], - [v], - [r], - [s], - [false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params, - 0 - ) - ) - .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') - .withArgs(weth.address, dai.address, flashloanAmount.toString(), expectedDaiAmount); - - const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const userADaiBalance = await aDai.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(userADaiBalance).to.be.eq(expectedDaiAmount); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); - }); - - it('should revert if inconsistent params', async () => { - const { users, weth, oracle, dai, aWETH, pool, uniswapLiquiditySwapAdapter } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); - - // User will swap liquidity 10 aEth to aDai - const liquidityToSwap = parseEther('10'); - await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); - - // Subtract the FL fee from the amount to be swapped 0,09% - const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); - - const params = buildLiquiditySwapParams( - [dai.address, weth.address], - [expectedDaiAmount], - [0], - [0], - [0], - [0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params, - 0 - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - - const params2 = buildLiquiditySwapParams( - [dai.address, weth.address], - [expectedDaiAmount], - [0, 0], - [0, 0], - [0, 0], - [0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params2, - 0 - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - - const params3 = buildLiquiditySwapParams( - [dai.address, weth.address], - [expectedDaiAmount], - [0, 0], - [0], - [0, 0], - [0, 0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params3, - 0 - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - - const params4 = buildLiquiditySwapParams( - [dai.address, weth.address], - [expectedDaiAmount], - [0], - [0], - [0], - [0], - [ - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - ], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params4, - 0 - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - - const params5 = buildLiquiditySwapParams( - [dai.address, weth.address], - [expectedDaiAmount], - [0], - [0], - [0], - [0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [ - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - ], - [false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params5, - 0 - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - - const params6 = buildLiquiditySwapParams( - [dai.address, weth.address], - [expectedDaiAmount, expectedDaiAmount], - [0], - [0], - [0], - [0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params6, - 0 - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - - const params7 = buildLiquiditySwapParams( - [dai.address], - [expectedDaiAmount], - [0, 0], - [0], - [0], - [0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params7, - 0 - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - - const params8 = buildLiquiditySwapParams( - [dai.address], - [expectedDaiAmount], - [0], - [0, 0], - [0], - [0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params8, - 0 - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - - const params9 = buildLiquiditySwapParams( - [dai.address], - [expectedDaiAmount], - [0], - [0], - [0], - [0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false, false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params9, - 0 - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - }); - - it('should revert if caller not lending pool', async () => { - const { users, weth, oracle, dai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); - - // User will swap liquidity 10 aEth to aDai - const liquidityToSwap = parseEther('10'); - await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); - - // Subtract the FL fee from the amount to be swapped 0,09% - const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); - - const params = buildLiquiditySwapParams( - [dai.address], - [expectedDaiAmount], - [0], - [0], - [0], - [0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false] - ); - - await expect( - uniswapLiquiditySwapAdapter - .connect(user) - .executeOperation( - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params - ) - ).to.be.revertedWith('CALLER_MUST_BE_LENDING_POOL'); - }); - - it('should work correctly with tokens of different decimals', async () => { - const { - users, - usdc, - oracle, - dai, - aDai, - uniswapLiquiditySwapAdapter, - pool, - deployer, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); - const liquidity = await convertToCurrencyDecimals(usdc.address, '20000'); - - // Provide liquidity - await usdc.mint(liquidity); - await usdc.approve(pool.address, liquidity); - await pool.deposit(usdc.address, liquidity, deployer.address, 0); - - // Make a deposit for user - await usdc.connect(user).mint(amountUSDCtoSwap); - await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); - await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); - - const usdcPrice = await oracle.getAssetPrice(usdc.address); - const daiPrice = await oracle.getAssetPrice(dai.address); - - // usdc 6 - const collateralDecimals = (await usdc.decimals()).toString(); - const principalDecimals = (await dai.decimals()).toString(); - - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountUSDCtoSwap.toString()) - .times( - new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) - ) - .div( - new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) - ) - .toFixed(0) - ); - - await mockUniswapRouter.connect(user).setAmountToReturn(usdc.address, expectedDaiAmount); - - const aUsdcData = await pool.getReserveData(usdc.address); - const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); - const aUsdcBalance = await aUsdc.balanceOf(userAddress); - await aUsdc.connect(user).approve(uniswapLiquiditySwapAdapter.address, aUsdcBalance); - // Subtract the FL fee from the amount to be swapped 0,09% - const flashloanAmount = new BigNumber(amountUSDCtoSwap.toString()).div(1.0009).toFixed(0); - - const params = buildLiquiditySwapParams( - [dai.address], - [expectedDaiAmount], - [0], - [0], - [0], - [0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [usdc.address], - [flashloanAmount.toString()], - [0], - userAddress, - params, - 0 - ) - ) - .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') - .withArgs(usdc.address, dai.address, flashloanAmount.toString(), expectedDaiAmount); - - const adapterUsdcBalance = await usdc.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const aDaiBalance = await aDai.balanceOf(userAddress); - - expect(adapterUsdcBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(aDaiBalance).to.be.eq(expectedDaiAmount); - }); - - it('should revert when min amount to receive exceeds the max slippage amount', async () => { - const { users, weth, oracle, dai, aWETH, pool, uniswapLiquiditySwapAdapter } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); - const smallExpectedDaiAmount = expectedDaiAmount.div(2); - - // User will swap liquidity 10 aEth to aDai - const liquidityToSwap = parseEther('10'); - await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); - - // Subtract the FL fee from the amount to be swapped 0,09% - const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); - - const params = buildLiquiditySwapParams( - [dai.address], - [smallExpectedDaiAmount], - [0], - [0], - [0], - [0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false] - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [flashloanAmount.toString()], - [0], - userAddress, - params, - 0 - ) - ).to.be.revertedWith('minAmountOut exceed max slippage'); - }); - - it('should correctly swap tokens all the balance', async () => { - const { - users, - weth, - oracle, - dai, - aDai, - aWETH, - pool, - uniswapLiquiditySwapAdapter, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); - - // Remove other balance - await aWETH.connect(user).transfer(users[1].address, parseEther('90')); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - // User will swap liquidity 10 aEth to aDai - const liquidityToSwap = parseEther('10'); - expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); - await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); - - const params = buildLiquiditySwapParams( - [dai.address], - [expectedDaiAmount], - [1], - [0], - [0], - [0], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - ['0x0000000000000000000000000000000000000000000000000000000000000000'], - [false] - ); - - // Flashloan + premium > aToken balance. Then it will only swap the balance - premium - const flashloanFee = liquidityToSwap.mul(9).div(10000); - const swappedAmount = liquidityToSwap.sub(flashloanFee); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [liquidityToSwap.toString()], - [0], - userAddress, - params, - 0 - ) - ) - .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') - .withArgs(weth.address, dai.address, swappedAmount.toString(), expectedDaiAmount); - - const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const userADaiBalance = await aDai.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(userADaiBalance).to.be.eq(expectedDaiAmount); - expect(userAEthBalance).to.be.eq(Zero); - expect(adapterAEthBalance).to.be.eq(Zero); - }); - - it('should correctly swap tokens all the balance using permit', async () => { - const { - users, - weth, - oracle, - dai, - aDai, - aWETH, - pool, - uniswapLiquiditySwapAdapter, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); - - // Remove other balance - await aWETH.connect(user).transfer(users[1].address, parseEther('90')); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - const liquidityToSwap = parseEther('10'); - expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const deadline = MAX_UINT_AMOUNT; - const nonce = (await aWETH._nonces(userAddress)).toNumber(); - const msgParams = buildPermitParams( - chainId, - aWETH.address, - '1', - await aWETH.name(), - userAddress, - uniswapLiquiditySwapAdapter.address, - nonce, - deadline, - liquidityToSwap.toString() - ); - - const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); - - const params = buildLiquiditySwapParams( - [dai.address], - [expectedDaiAmount], - [1], - [liquidityToSwap], - [deadline], - [v], - [r], - [s], - [false] - ); - - // Flashloan + premium > aToken balance. Then it will only swap the balance - premium - const flashloanFee = liquidityToSwap.mul(9).div(10000); - const swappedAmount = liquidityToSwap.sub(flashloanFee); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapLiquiditySwapAdapter.address, - [weth.address], - [liquidityToSwap.toString()], - [0], - userAddress, - params, - 0 - ) - ) - .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') - .withArgs(weth.address, dai.address, swappedAmount.toString(), expectedDaiAmount); - - const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const userADaiBalance = await aDai.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(userADaiBalance).to.be.eq(expectedDaiAmount); - expect(userAEthBalance).to.be.eq(Zero); - expect(adapterAEthBalance).to.be.eq(Zero); - }); - }); - - describe('swapAndDeposit', () => { - beforeEach(async () => { - const { users, weth, dai, pool, deployer } = testEnv; - const userAddress = users[0].address; - - // Provide liquidity - await dai.mint(parseEther('20000')); - await dai.approve(pool.address, parseEther('20000')); - await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); - - // Make a deposit for user - await weth.mint(parseEther('100')); - await weth.approve(pool.address, parseEther('100')); - await pool.deposit(weth.address, parseEther('100'), userAddress, 0); - }); - - it('should correctly swap tokens and deposit the out tokens in the pool', async () => { - const { users, weth, oracle, dai, aDai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); - - // User will swap liquidity 10 aEth to aDai - const liquidityToSwap = parseEther('10'); - await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - await expect( - uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( - [weth.address], - [dai.address], - [amountWETHtoSwap], - [expectedDaiAmount], - [ - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - ], - [false] - ) - ) - .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') - .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); - - const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const userADaiBalance = await aDai.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(userADaiBalance).to.be.eq(expectedDaiAmount); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); - }); - - it('should correctly swap tokens using permit', async () => { - const { users, weth, oracle, dai, aDai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); - - // User will swap liquidity 10 aEth to aDai - const liquidityToSwap = parseEther('10'); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const deadline = MAX_UINT_AMOUNT; - const nonce = (await aWETH._nonces(userAddress)).toNumber(); - const msgParams = buildPermitParams( - chainId, - aWETH.address, - '1', - await aWETH.name(), - userAddress, - uniswapLiquiditySwapAdapter.address, - nonce, - deadline, - liquidityToSwap.toString() - ); - - const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); - - await expect( - uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( - [weth.address], - [dai.address], - [amountWETHtoSwap], - [expectedDaiAmount], - [ - { - amount: liquidityToSwap, - deadline, - v, - r, - s, - }, - ], - [false] - ) - ) - .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') - .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); - - const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const userADaiBalance = await aDai.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(userADaiBalance).to.be.eq(expectedDaiAmount); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); - }); - - it('should revert if inconsistent params', async () => { - const { users, weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv; - const user = users[0].signer; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await expect( - uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( - [weth.address, dai.address], - [dai.address], - [amountWETHtoSwap], - [expectedDaiAmount], - [ - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - ], - [false] - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - - await expect( - uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( - [weth.address], - [dai.address, weth.address], - [amountWETHtoSwap], - [expectedDaiAmount], - [ - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - ], - [false] - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - - await expect( - uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( - [weth.address], - [dai.address], - [amountWETHtoSwap, amountWETHtoSwap], - [expectedDaiAmount], - [ - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - ], - [false] - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - - await expect( - uniswapLiquiditySwapAdapter - .connect(user) - .swapAndDeposit( - [weth.address], - [dai.address], - [amountWETHtoSwap], - [expectedDaiAmount], - [], - [false] - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - - await expect( - uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( - [weth.address], - [dai.address], - [amountWETHtoSwap], - [expectedDaiAmount, expectedDaiAmount], - [ - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - ], - [false] - ) - ).to.be.revertedWith('INCONSISTENT_PARAMS'); - }); - - it('should revert when min amount to receive exceeds the max slippage amount', async () => { - const { users, weth, oracle, dai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; - const user = users[0].signer; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); - const smallExpectedDaiAmount = expectedDaiAmount.div(2); - - // User will swap liquidity 10 aEth to aDai - const liquidityToSwap = parseEther('10'); - await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); - - await expect( - uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( - [weth.address], - [dai.address], - [amountWETHtoSwap], - [smallExpectedDaiAmount], - [ - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - ], - [false] - ) - ).to.be.revertedWith('minAmountOut exceed max slippage'); - }); - - it('should correctly swap tokens and deposit multiple tokens', async () => { - const { - users, - weth, - usdc, - oracle, - dai, - aDai, - aWETH, - uniswapLiquiditySwapAdapter, - pool, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmountForEth = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); - const usdcPrice = await oracle.getAssetPrice(usdc.address); - - const collateralDecimals = (await usdc.decimals()).toString(); - const principalDecimals = (await dai.decimals()).toString(); - - const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountUSDCtoSwap.toString()) - .times( - new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) - ) - .div( - new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) - ) - .toFixed(0) - ); - - // Make a deposit for user - await usdc.connect(user).mint(amountUSDCtoSwap); - await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); - await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); - - const aUsdcData = await pool.getReserveData(usdc.address); - const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); - await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); - - await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountWETHtoSwap); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - await aUsdc.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountUSDCtoSwap); - const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); - - await uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( - [weth.address, usdc.address], - [dai.address, dai.address], - [amountWETHtoSwap, amountUSDCtoSwap], - [expectedDaiAmountForEth, expectedDaiAmountForUsdc], - [ - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - ], - [false, false] - ); - - const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const userADaiBalance = await aDai.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const userAUsdcBalance = await aUsdc.balanceOf(userAddress); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); - expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); - expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); - }); - - it('should correctly swap tokens and deposit multiple tokens using permit', async () => { - const { - users, - weth, - usdc, - oracle, - dai, - aDai, - aWETH, - uniswapLiquiditySwapAdapter, - pool, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const deadline = MAX_UINT_AMOUNT; - - const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmountForEth = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); - const usdcPrice = await oracle.getAssetPrice(usdc.address); - - const collateralDecimals = (await usdc.decimals()).toString(); - const principalDecimals = (await dai.decimals()).toString(); - - const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountUSDCtoSwap.toString()) - .times( - new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) - ) - .div( - new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) - ) - .toFixed(0) - ); - - // Make a deposit for user - await usdc.connect(user).mint(amountUSDCtoSwap); - await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); - await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); - - const aUsdcData = await pool.getReserveData(usdc.address); - const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); - await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); - - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); - - const aWethNonce = (await aWETH._nonces(userAddress)).toNumber(); - const aWethMsgParams = buildPermitParams( - chainId, - aWETH.address, - '1', - await aWETH.name(), - userAddress, - uniswapLiquiditySwapAdapter.address, - aWethNonce, - deadline, - amountWETHtoSwap.toString() - ); - const { v: aWETHv, r: aWETHr, s: aWETHs } = getSignatureFromTypedData( - ownerPrivateKey, - aWethMsgParams - ); - - const aUsdcNonce = (await aUsdc._nonces(userAddress)).toNumber(); - const aUsdcMsgParams = buildPermitParams( - chainId, - aUsdc.address, - '1', - await aUsdc.name(), - userAddress, - uniswapLiquiditySwapAdapter.address, - aUsdcNonce, - deadline, - amountUSDCtoSwap.toString() - ); - const { v: aUsdcv, r: aUsdcr, s: aUsdcs } = getSignatureFromTypedData( - ownerPrivateKey, - aUsdcMsgParams - ); - - await uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( - [weth.address, usdc.address], - [dai.address, dai.address], - [amountWETHtoSwap, amountUSDCtoSwap], - [expectedDaiAmountForEth, expectedDaiAmountForUsdc], - [ - { - amount: amountWETHtoSwap, - deadline, - v: aWETHv, - r: aWETHr, - s: aWETHs, - }, - { - amount: amountUSDCtoSwap, - deadline, - v: aUsdcv, - r: aUsdcr, - s: aUsdcs, - }, - ], - [false, false] - ); - - const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const userADaiBalance = await aDai.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const userAUsdcBalance = await aUsdc.balanceOf(userAddress); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); - expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); - expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); - }); - - it('should correctly swap all the balance when using a bigger amount', async () => { - const { users, weth, oracle, dai, aDai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); - - // Remove other balance - await aWETH.connect(user).transfer(users[1].address, parseEther('90')); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - // User will swap liquidity 10 aEth to aDai - const liquidityToSwap = parseEther('10'); - expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); - - // User will swap liquidity 10 aEth to aDai - await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); - - // Only has 10 atokens, so all the balance will be swapped - const bigAmountToSwap = parseEther('100'); - - await expect( - uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( - [weth.address], - [dai.address], - [bigAmountToSwap], - [expectedDaiAmount], - [ - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - ], - [false] - ) - ) - .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') - .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); - - const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const userADaiBalance = await aDai.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(userADaiBalance).to.be.eq(expectedDaiAmount); - expect(userAEthBalance).to.be.eq(Zero); - expect(adapterAEthBalance).to.be.eq(Zero); - }); - - it('should correctly swap all the balance when using permit', async () => { - const { users, weth, oracle, dai, aDai, aWETH, uniswapLiquiditySwapAdapter } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); - - // Remove other balance - await aWETH.connect(user).transfer(users[1].address, parseEther('90')); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - // User will swap liquidity 10 aEth to aDai - const liquidityToSwap = parseEther('10'); - expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); - - // Only has 10 atokens, so all the balance will be swapped - const bigAmountToSwap = parseEther('100'); - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const deadline = MAX_UINT_AMOUNT; - - const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - const aWethNonce = (await aWETH._nonces(userAddress)).toNumber(); - const aWethMsgParams = buildPermitParams( - chainId, - aWETH.address, - '1', - await aWETH.name(), - userAddress, - uniswapLiquiditySwapAdapter.address, - aWethNonce, - deadline, - bigAmountToSwap.toString() - ); - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, aWethMsgParams); - - await expect( - uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( - [weth.address], - [dai.address], - [bigAmountToSwap], - [expectedDaiAmount], - [ - { - amount: bigAmountToSwap, - deadline, - v, - r, - s, - }, - ], - [false] - ) - ) - .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') - .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); - - const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); - const adapterDaiAllowance = await dai.allowance( - uniswapLiquiditySwapAdapter.address, - userAddress - ); - const userADaiBalance = await aDai.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(adapterDaiAllowance).to.be.eq(Zero); - expect(userADaiBalance).to.be.eq(expectedDaiAmount); - expect(userAEthBalance).to.be.eq(Zero); - expect(adapterAEthBalance).to.be.eq(Zero); - }); - }); - }); -}); diff --git a/test/uniswapAdapters.repay.spec.ts b/test/uniswapAdapters.repay.spec.ts deleted file mode 100644 index c271917e..00000000 --- a/test/uniswapAdapters.repay.spec.ts +++ /dev/null @@ -1,1469 +0,0 @@ -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { - convertToCurrencyDecimals, - getContract, - buildPermitParams, - getSignatureFromTypedData, - buildRepayAdapterParams, -} from '../helpers/contracts-helpers'; -import { getMockUniswapRouter } from '../helpers/contracts-getters'; -import { deployUniswapRepayAdapter } from '../helpers/contracts-deployments'; -import { MockUniswapV2Router02 } from '../types/MockUniswapV2Router02'; -import { Zero } from '@ethersproject/constants'; -import BigNumber from 'bignumber.js'; -import { DRE, evmRevert, evmSnapshot } from '../helpers/misc-utils'; -import { ethers } from 'ethers'; -import { eContractid } from '../helpers/types'; -import { StableDebtToken } from '../types/StableDebtToken'; -import { BUIDLEREVM_CHAINID } from '../helpers/buidler-constants'; -import { MAX_UINT_AMOUNT } from '../helpers/constants'; -import { VariableDebtToken } from '../types'; -const { parseEther } = ethers.utils; - -const { expect } = require('chai'); - -makeSuite('Uniswap adapters', (testEnv: TestEnv) => { - let mockUniswapRouter: MockUniswapV2Router02; - let evmSnapshotId: string; - - before(async () => { - mockUniswapRouter = await getMockUniswapRouter(); - }); - - beforeEach(async () => { - evmSnapshotId = await evmSnapshot(); - }); - - afterEach(async () => { - await evmRevert(evmSnapshotId); - }); - - describe('UniswapRepayAdapter', () => { - beforeEach(async () => { - const { users, weth, dai, usdc, aave, pool, deployer } = testEnv; - const userAddress = users[0].address; - - // Provide liquidity - await dai.mint(parseEther('20000')); - await dai.approve(pool.address, parseEther('20000')); - await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); - - const usdcLiquidity = await convertToCurrencyDecimals(usdc.address, '2000000'); - await usdc.mint(usdcLiquidity); - await usdc.approve(pool.address, usdcLiquidity); - await pool.deposit(usdc.address, usdcLiquidity, deployer.address, 0); - - await weth.mint(parseEther('100')); - await weth.approve(pool.address, parseEther('100')); - await pool.deposit(weth.address, parseEther('100'), deployer.address, 0); - - await aave.mint(parseEther('1000000')); - await aave.approve(pool.address, parseEther('1000000')); - await pool.deposit(aave.address, parseEther('1000000'), deployer.address, 0); - - // Make a deposit for user - await weth.mint(parseEther('1000')); - await weth.approve(pool.address, parseEther('1000')); - await pool.deposit(weth.address, parseEther('1000'), userAddress, 0); - - await aave.mint(parseEther('1000000')); - await aave.approve(pool.address, parseEther('1000000')); - await pool.deposit(aave.address, parseEther('1000000'), userAddress, 0); - - await usdc.mint(usdcLiquidity); - await usdc.approve(pool.address, usdcLiquidity); - await pool.deposit(usdc.address, usdcLiquidity, userAddress, 0); - }); - - describe('constructor', () => { - it('should deploy with correct parameters', async () => { - const { addressesProvider, weth } = testEnv; - await deployUniswapRepayAdapter([ - addressesProvider.address, - mockUniswapRouter.address, - weth.address, - ]); - }); - - it('should revert if not valid addresses provider', async () => { - const { weth } = testEnv; - expect( - deployUniswapRepayAdapter([ - mockUniswapRouter.address, - mockUniswapRouter.address, - weth.address, - ]) - ).to.be.reverted; - }); - }); - - describe('executeOperation', () => { - it('should correctly swap tokens and repay debt', async () => { - const { - users, - pool, - weth, - aWETH, - oracle, - dai, - uniswapRepayAdapter, - helpersContract, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); - - const daiStableDebtTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).stableDebtTokenAddress; - - const daiStableDebtContract = await getContract( - eContractid.StableDebtToken, - daiStableDebtTokenAddress - ); - - const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); - - const liquidityToSwap = amountWETHtoSwap; - await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); - - const flashLoanDebt = new BigNumber(expectedDaiAmount.toString()) - .multipliedBy(1.0009) - .toFixed(0); - - await mockUniswapRouter.setAmountIn( - flashLoanDebt, - weth.address, - dai.address, - liquidityToSwap - ); - - const params = buildRepayAdapterParams( - weth.address, - liquidityToSwap, - 1, - 0, - 0, - 0, - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - false - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapRepayAdapter.address, - [dai.address], - [expectedDaiAmount.toString()], - [0], - userAddress, - params, - 0 - ) - ) - .to.emit(uniswapRepayAdapter, 'Swapped') - .withArgs(weth.address, dai.address, liquidityToSwap.toString(), flashLoanDebt); - - const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); - expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); - }); - - it('should correctly swap tokens and repay debt with permit', async () => { - const { - users, - pool, - weth, - aWETH, - oracle, - dai, - uniswapRepayAdapter, - helpersContract, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); - - const daiStableDebtTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).stableDebtTokenAddress; - - const daiStableDebtContract = await getContract( - eContractid.StableDebtToken, - daiStableDebtTokenAddress - ); - - const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); - - const liquidityToSwap = amountWETHtoSwap; - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const deadline = MAX_UINT_AMOUNT; - const nonce = (await aWETH._nonces(userAddress)).toNumber(); - const msgParams = buildPermitParams( - chainId, - aWETH.address, - '1', - await aWETH.name(), - userAddress, - uniswapRepayAdapter.address, - nonce, - deadline, - liquidityToSwap.toString() - ); - - const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); - - const flashLoanDebt = new BigNumber(expectedDaiAmount.toString()) - .multipliedBy(1.0009) - .toFixed(0); - - await mockUniswapRouter.setAmountIn( - flashLoanDebt, - weth.address, - dai.address, - liquidityToSwap - ); - - const params = buildRepayAdapterParams( - weth.address, - liquidityToSwap, - 1, - liquidityToSwap, - deadline, - v, - r, - s, - false - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapRepayAdapter.address, - [dai.address], - [expectedDaiAmount.toString()], - [0], - userAddress, - params, - 0 - ) - ) - .to.emit(uniswapRepayAdapter, 'Swapped') - .withArgs(weth.address, dai.address, liquidityToSwap.toString(), flashLoanDebt); - - const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); - expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); - }); - - it('should revert if caller not lending pool', async () => { - const { users, pool, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); - - const liquidityToSwap = amountWETHtoSwap; - await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); - - const params = buildRepayAdapterParams( - weth.address, - liquidityToSwap, - 1, - 0, - 0, - 0, - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - false - ); - - await expect( - uniswapRepayAdapter - .connect(user) - .executeOperation( - [dai.address], - [expectedDaiAmount.toString()], - [0], - userAddress, - params - ) - ).to.be.revertedWith('CALLER_MUST_BE_LENDING_POOL'); - }); - - it('should revert if there is not debt to repay with the specified rate mode', async () => { - const { users, pool, weth, oracle, dai, uniswapRepayAdapter, aWETH } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - await weth.connect(user).mint(amountWETHtoSwap); - await weth.connect(user).transfer(uniswapRepayAdapter.address, amountWETHtoSwap); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress); - - const liquidityToSwap = amountWETHtoSwap; - await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); - - const params = buildRepayAdapterParams( - weth.address, - liquidityToSwap, - 1, - 0, - 0, - 0, - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - false - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapRepayAdapter.address, - [dai.address], - [expectedDaiAmount.toString()], - [0], - userAddress, - params, - 0 - ) - ).to.be.reverted; - }); - - it('should revert if there is not debt to repay', async () => { - const { users, pool, weth, oracle, dai, uniswapRepayAdapter, aWETH } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - await weth.connect(user).mint(amountWETHtoSwap); - await weth.connect(user).transfer(uniswapRepayAdapter.address, amountWETHtoSwap); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - const liquidityToSwap = amountWETHtoSwap; - await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap); - - const params = buildRepayAdapterParams( - weth.address, - liquidityToSwap, - 1, - 0, - 0, - 0, - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - false - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapRepayAdapter.address, - [dai.address], - [expectedDaiAmount.toString()], - [0], - userAddress, - params, - 0 - ) - ).to.be.reverted; - }); - - it('should revert when max amount allowed to swap is bigger than max slippage', async () => { - const { users, pool, weth, oracle, dai, aWETH, uniswapRepayAdapter } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); - - const bigMaxAmountToSwap = amountWETHtoSwap.mul(2); - await aWETH.connect(user).approve(uniswapRepayAdapter.address, bigMaxAmountToSwap); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, bigMaxAmountToSwap); - - const flashLoanDebt = new BigNumber(expectedDaiAmount.toString()) - .multipliedBy(1.0009) - .toFixed(0); - - await mockUniswapRouter.setAmountIn( - flashLoanDebt, - weth.address, - dai.address, - bigMaxAmountToSwap - ); - - const params = buildRepayAdapterParams( - weth.address, - bigMaxAmountToSwap, - 1, - 0, - 0, - 0, - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - false - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapRepayAdapter.address, - [dai.address], - [expectedDaiAmount.toString()], - [0], - userAddress, - params, - 0 - ) - ).to.be.revertedWith('maxAmountToSwap exceed max slippage'); - }); - - it('should swap, repay debt and pull the needed ATokens leaving no leftovers', async () => { - const { - users, - pool, - weth, - aWETH, - oracle, - dai, - uniswapRepayAdapter, - helpersContract, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); - - const daiStableDebtTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).stableDebtTokenAddress; - - const daiStableDebtContract = await getContract( - eContractid.StableDebtToken, - daiStableDebtTokenAddress - ); - - const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); - - const liquidityToSwap = amountWETHtoSwap; - await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - const userWethBalanceBefore = await weth.balanceOf(userAddress); - - const actualWEthSwapped = new BigNumber(liquidityToSwap.toString()) - .multipliedBy(0.995) - .toFixed(0); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped); - - const flashLoanDebt = new BigNumber(expectedDaiAmount.toString()) - .multipliedBy(1.0009) - .toFixed(0); - - await mockUniswapRouter.setAmountIn( - flashLoanDebt, - weth.address, - dai.address, - actualWEthSwapped - ); - - const params = buildRepayAdapterParams( - weth.address, - liquidityToSwap, - 1, - 0, - 0, - 0, - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - false - ); - - await expect( - pool - .connect(user) - .flashLoan( - uniswapRepayAdapter.address, - [dai.address], - [expectedDaiAmount.toString()], - [0], - userAddress, - params, - 0 - ) - ) - .to.emit(uniswapRepayAdapter, 'Swapped') - .withArgs(weth.address, dai.address, actualWEthSwapped.toString(), flashLoanDebt); - - const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); - const userWethBalance = await weth.balanceOf(userAddress); - - expect(adapterAEthBalance).to.be.eq(Zero); - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); - expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(actualWEthSwapped)); - expect(userWethBalance).to.be.eq(userWethBalanceBefore); - }); - - it('should correctly swap tokens and repay the whole stable debt', async () => { - const { - users, - pool, - weth, - aWETH, - oracle, - dai, - uniswapRepayAdapter, - helpersContract, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); - - const daiStableDebtTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).stableDebtTokenAddress; - - const daiStableDebtContract = await getContract( - eContractid.StableDebtToken, - daiStableDebtTokenAddress - ); - - const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); - - // Add a % to repay on top of the debt - const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString()) - .multipliedBy(1.1) - .toFixed(0); - - await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - // Add a % to repay on top of the debt - const amountToRepay = new BigNumber(expectedDaiAmount.toString()) - .multipliedBy(1.1) - .toFixed(0); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap); - await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap); - - const params = buildRepayAdapterParams( - weth.address, - liquidityToSwap, - 1, - 0, - 0, - 0, - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - false - ); - - await pool - .connect(user) - .flashLoan( - uniswapRepayAdapter.address, - [dai.address], - [amountToRepay.toString()], - [0], - userAddress, - params, - 0 - ); - - const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); - - expect(adapterAEthBalance).to.be.eq(Zero); - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); - expect(userDaiStableDebtAmount).to.be.eq(Zero); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); - }); - - it('should correctly swap tokens and repay the whole variable debt', async () => { - const { - users, - pool, - weth, - aWETH, - oracle, - dai, - uniswapRepayAdapter, - helpersContract, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress); - - const daiStableVariableTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).variableDebtTokenAddress; - - const daiVariableDebtContract = await getContract( - eContractid.VariableDebtToken, - daiStableVariableTokenAddress - ); - - const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( - userAddress - ); - - // Add a % to repay on top of the debt - const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString()) - .multipliedBy(1.1) - .toFixed(0); - - await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - // Add a % to repay on top of the debt - const amountToRepay = new BigNumber(expectedDaiAmount.toString()) - .multipliedBy(1.1) - .toFixed(0); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap); - await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap); - - const params = buildRepayAdapterParams( - weth.address, - liquidityToSwap, - 2, - 0, - 0, - 0, - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - false - ); - - await pool - .connect(user) - .flashLoan( - uniswapRepayAdapter.address, - [dai.address], - [amountToRepay.toString()], - [0], - userAddress, - params, - 0 - ); - - const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); - - expect(adapterAEthBalance).to.be.eq(Zero); - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(userDaiVariableDebtAmountBefore).to.be.gte(expectedDaiAmount); - expect(userDaiVariableDebtAmount).to.be.eq(Zero); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); - }); - - it('should correctly repay debt via flash loan using the same asset as collateral', async () => { - const { users, pool, aDai, dai, uniswapRepayAdapter, helpersContract } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - // Add deposit for user - await dai.mint(parseEther('30')); - await dai.approve(pool.address, parseEther('30')); - await pool.deposit(dai.address, parseEther('30'), userAddress, 0); - - const amountCollateralToSwap = parseEther('10'); - const debtAmount = parseEther('10'); - - // Open user Debt - await pool.connect(user).borrow(dai.address, debtAmount, 2, 0, userAddress); - - const daiVariableDebtTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).variableDebtTokenAddress; - - const daiVariableDebtContract = await getContract( - eContractid.VariableDebtToken, - daiVariableDebtTokenAddress - ); - - const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( - userAddress - ); - - const flashLoanDebt = new BigNumber(amountCollateralToSwap.toString()) - .multipliedBy(1.0009) - .toFixed(0); - - await aDai.connect(user).approve(uniswapRepayAdapter.address, flashLoanDebt); - const userADaiBalanceBefore = await aDai.balanceOf(userAddress); - const userDaiBalanceBefore = await dai.balanceOf(userAddress); - - const params = buildRepayAdapterParams( - dai.address, - amountCollateralToSwap, - 2, - 0, - 0, - 0, - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - false - ); - - await pool - .connect(user) - .flashLoan( - uniswapRepayAdapter.address, - [dai.address], - [amountCollateralToSwap.toString()], - [0], - userAddress, - params, - 0 - ); - - const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); - const userADaiBalance = await aDai.balanceOf(userAddress); - const adapterADaiBalance = await aDai.balanceOf(uniswapRepayAdapter.address); - const userDaiBalance = await dai.balanceOf(userAddress); - - expect(adapterADaiBalance).to.be.eq(Zero, 'adapter aDAI balance should be zero'); - expect(adapterDaiBalance).to.be.eq(Zero, 'adapter DAI balance should be zero'); - expect(userDaiVariableDebtAmountBefore).to.be.gte( - debtAmount, - ' user DAI variable debt before should be gte debtAmount' - ); - expect(userDaiVariableDebtAmount).to.be.lt( - debtAmount, - 'user dai variable debt amount should be lt debt amount' - ); - expect(userADaiBalance).to.be.lt( - userADaiBalanceBefore, - 'user aDAI balance should be lt aDAI prior balance' - ); - expect(userADaiBalance).to.be.gte( - userADaiBalanceBefore.sub(flashLoanDebt), - 'user aDAI balance should be gte aDAI prior balance sub flash loan debt' - ); - expect(userDaiBalance).to.be.eq(userDaiBalanceBefore, 'user dai balance eq prior balance'); - }); - }); - - describe('swapAndRepay', () => { - it('should correctly swap tokens and repay debt', async () => { - const { - users, - pool, - weth, - aWETH, - oracle, - dai, - uniswapRepayAdapter, - helpersContract, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); - - const daiStableDebtTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).stableDebtTokenAddress; - - const daiStableDebtContract = await getContract( - eContractid.StableDebtToken, - daiStableDebtTokenAddress - ); - - const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); - - const liquidityToSwap = amountWETHtoSwap; - await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap); - - await mockUniswapRouter.setDefaultMockValue(liquidityToSwap); - - await uniswapRepayAdapter.connect(user).swapAndRepay( - weth.address, - dai.address, - liquidityToSwap, - expectedDaiAmount, - 1, - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - false - ); - - const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); - expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); - }); - - it('should correctly swap tokens and repay debt with permit', async () => { - const { - users, - pool, - weth, - aWETH, - oracle, - dai, - uniswapRepayAdapter, - helpersContract, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); - - const daiStableDebtTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).stableDebtTokenAddress; - - const daiStableDebtContract = await getContract( - eContractid.StableDebtToken, - daiStableDebtTokenAddress - ); - - const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); - - const liquidityToSwap = amountWETHtoSwap; - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap); - - await mockUniswapRouter.setDefaultMockValue(liquidityToSwap); - - const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID; - const deadline = MAX_UINT_AMOUNT; - const nonce = (await aWETH._nonces(userAddress)).toNumber(); - const msgParams = buildPermitParams( - chainId, - aWETH.address, - '1', - await aWETH.name(), - userAddress, - uniswapRepayAdapter.address, - nonce, - deadline, - liquidityToSwap.toString() - ); - - const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey; - if (!ownerPrivateKey) { - throw new Error('INVALID_OWNER_PK'); - } - - const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams); - - await uniswapRepayAdapter.connect(user).swapAndRepay( - weth.address, - dai.address, - liquidityToSwap, - expectedDaiAmount, - 1, - { - amount: liquidityToSwap, - deadline, - v, - r, - s, - }, - false - ); - - const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); - expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); - }); - - it('should revert if there is not debt to repay', async () => { - const { users, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv; - const user = users[0].signer; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - const liquidityToSwap = amountWETHtoSwap; - await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); - - await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap); - - await mockUniswapRouter.setDefaultMockValue(liquidityToSwap); - - await expect( - uniswapRepayAdapter.connect(user).swapAndRepay( - weth.address, - dai.address, - liquidityToSwap, - expectedDaiAmount, - 1, - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - false - ) - ).to.be.reverted; - }); - - it('should revert when max amount allowed to swap is bigger than max slippage', async () => { - const { users, pool, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); - - const bigMaxAmountToSwap = amountWETHtoSwap.mul(2); - await aWETH.connect(user).approve(uniswapRepayAdapter.address, bigMaxAmountToSwap); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, bigMaxAmountToSwap); - - await mockUniswapRouter.setDefaultMockValue(bigMaxAmountToSwap); - - await expect( - uniswapRepayAdapter.connect(user).swapAndRepay( - weth.address, - dai.address, - bigMaxAmountToSwap, - expectedDaiAmount, - 1, - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - false - ) - ).to.be.revertedWith('maxAmountToSwap exceed max slippage'); - }); - - it('should swap, repay debt and pull the needed ATokens leaving no leftovers', async () => { - const { - users, - pool, - weth, - aWETH, - oracle, - dai, - uniswapRepayAdapter, - helpersContract, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); - - const daiStableDebtTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).stableDebtTokenAddress; - - const daiStableDebtContract = await getContract( - eContractid.StableDebtToken, - daiStableDebtTokenAddress - ); - - const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); - - const liquidityToSwap = amountWETHtoSwap; - await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - const userWethBalanceBefore = await weth.balanceOf(userAddress); - - const actualWEthSwapped = new BigNumber(liquidityToSwap.toString()) - .multipliedBy(0.995) - .toFixed(0); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped); - - await mockUniswapRouter.setDefaultMockValue(actualWEthSwapped); - - await uniswapRepayAdapter.connect(user).swapAndRepay( - weth.address, - dai.address, - liquidityToSwap, - expectedDaiAmount, - 1, - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - false - ); - - const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); - const userWethBalance = await weth.balanceOf(userAddress); - - expect(adapterAEthBalance).to.be.eq(Zero); - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); - expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(actualWEthSwapped)); - expect(userWethBalance).to.be.eq(userWethBalanceBefore); - }); - - it('should correctly swap tokens and repay the whole stable debt', async () => { - const { - users, - pool, - weth, - aWETH, - oracle, - dai, - uniswapRepayAdapter, - helpersContract, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress); - - const daiStableDebtTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).stableDebtTokenAddress; - - const daiStableDebtContract = await getContract( - eContractid.StableDebtToken, - daiStableDebtTokenAddress - ); - - const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); - - // Add a % to repay on top of the debt - const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString()) - .multipliedBy(1.1) - .toFixed(0); - - await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - // Add a % to repay on top of the debt - const amountToRepay = new BigNumber(expectedDaiAmount.toString()) - .multipliedBy(1.1) - .toFixed(0); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap); - await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap); - - await uniswapRepayAdapter.connect(user).swapAndRepay( - weth.address, - dai.address, - liquidityToSwap, - amountToRepay, - 1, - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - false - ); - - const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); - - expect(adapterAEthBalance).to.be.eq(Zero); - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount); - expect(userDaiStableDebtAmount).to.be.eq(Zero); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); - }); - - it('should correctly swap tokens and repay the whole variable debt', async () => { - const { - users, - pool, - weth, - aWETH, - oracle, - dai, - uniswapRepayAdapter, - helpersContract, - } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); - - const daiPrice = await oracle.getAssetPrice(dai.address); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) - ); - - // Open user Debt - await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress); - - const daiStableVariableTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).variableDebtTokenAddress; - - const daiVariableDebtContract = await getContract( - eContractid.VariableDebtToken, - daiStableVariableTokenAddress - ); - - const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( - userAddress - ); - - // Add a % to repay on top of the debt - const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString()) - .multipliedBy(1.1) - .toFixed(0); - - await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap); - const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); - - // Add a % to repay on top of the debt - const amountToRepay = new BigNumber(expectedDaiAmount.toString()) - .multipliedBy(1.1) - .toFixed(0); - - await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap); - await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap); - - await uniswapRepayAdapter.connect(user).swapAndRepay( - weth.address, - dai.address, - liquidityToSwap, - amountToRepay, - 2, - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - false - ); - - const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); - const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); - const userAEthBalance = await aWETH.balanceOf(userAddress); - const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address); - - expect(adapterAEthBalance).to.be.eq(Zero); - expect(adapterWethBalance).to.be.eq(Zero); - expect(adapterDaiBalance).to.be.eq(Zero); - expect(userDaiVariableDebtAmountBefore).to.be.gte(expectedDaiAmount); - expect(userDaiVariableDebtAmount).to.be.eq(Zero); - expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); - expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); - }); - - it('should correctly repay debt using the same asset as collateral', async () => { - const { users, pool, dai, uniswapRepayAdapter, helpersContract, aDai } = testEnv; - const user = users[0].signer; - const userAddress = users[0].address; - - // Add deposit for user - await dai.mint(parseEther('30')); - await dai.approve(pool.address, parseEther('30')); - await pool.deposit(dai.address, parseEther('30'), userAddress, 0); - - const amountCollateralToSwap = parseEther('4'); - - const debtAmount = parseEther('3'); - - // Open user Debt - await pool.connect(user).borrow(dai.address, debtAmount, 2, 0, userAddress); - - const daiVariableDebtTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).variableDebtTokenAddress; - - const daiVariableDebtContract = await getContract( - eContractid.StableDebtToken, - daiVariableDebtTokenAddress - ); - - const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf( - userAddress - ); - - await aDai.connect(user).approve(uniswapRepayAdapter.address, amountCollateralToSwap); - const userADaiBalanceBefore = await aDai.balanceOf(userAddress); - const userDaiBalanceBefore = await dai.balanceOf(userAddress); - - await uniswapRepayAdapter.connect(user).swapAndRepay( - dai.address, - dai.address, - amountCollateralToSwap, - amountCollateralToSwap, - 2, - { - amount: 0, - deadline: 0, - v: 0, - r: '0x0000000000000000000000000000000000000000000000000000000000000000', - s: '0x0000000000000000000000000000000000000000000000000000000000000000', - }, - false - ); - - const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); - const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress); - const userADaiBalance = await aDai.balanceOf(userAddress); - const adapterADaiBalance = await aDai.balanceOf(uniswapRepayAdapter.address); - const userDaiBalance = await dai.balanceOf(userAddress); - - expect(adapterADaiBalance).to.be.eq(Zero, 'adapter aADAI should be zero'); - expect(adapterDaiBalance).to.be.eq(Zero, 'adapter DAI should be zero'); - expect(userDaiVariableDebtAmountBefore).to.be.gte( - debtAmount, - 'user dai variable debt before should be gte debtAmount' - ); - expect(userDaiVariableDebtAmount).to.be.lt( - debtAmount, - 'current user dai variable debt amount should be less than debtAmount' - ); - expect(userADaiBalance).to.be.lt( - userADaiBalanceBefore, - 'current user aDAI balance should be less than prior balance' - ); - expect(userADaiBalance).to.be.gte( - userADaiBalanceBefore.sub(amountCollateralToSwap), - 'current user aDAI balance should be gte user balance sub swapped collateral' - ); - expect(userDaiBalance).to.be.eq( - userDaiBalanceBefore, - 'user DAI balance should remain equal' - ); - }); - }); - }); -}); diff --git a/test/upgradeability.spec.ts b/test/upgradeability.spec.ts deleted file mode 100644 index 95e3a8fe..00000000 --- a/test/upgradeability.spec.ts +++ /dev/null @@ -1,234 +0,0 @@ -import { expect } from 'chai'; -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { ProtocolErrors, eContractid } from '../helpers/types'; -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, - getMockStableDebtToken, - getMockVariableDebtToken, - getStableDebtToken, - getVariableDebtToken, -} from '../helpers/contracts-getters'; -import { - deployMockAToken, - deployMockStableDebtToken, - deployMockVariableDebtToken, -} from '../helpers/contracts-deployments'; - -makeSuite('Upgradeability', (testEnv: TestEnv) => { - const { CALLER_NOT_POOL_ADMIN } = ProtocolErrors; - let newATokenAddress: string; - let newStableTokenAddress: string; - let newVariableTokenAddress: string; - - before('deploying instances', async () => { - const { dai, pool } = testEnv; - const aTokenInstance = await deployMockAToken([ - pool.address, - dai.address, - ZERO_ADDRESS, - ZERO_ADDRESS, - 'Aave Interest bearing DAI updated', - 'aDAI', - ]); - - const stableDebtTokenInstance = await deployMockStableDebtToken([ - pool.address, - dai.address, - ZERO_ADDRESS, - 'Aave stable debt bearing DAI updated', - 'stableDebtDAI', - ]); - - const variableDebtTokenInstance = await deployMockVariableDebtToken([ - pool.address, - dai.address, - ZERO_ADDRESS, - 'Aave variable debt bearing DAI updated', - 'variableDebtDAI', - ]); - - newATokenAddress = aTokenInstance.address; - newVariableTokenAddress = variableDebtTokenInstance.address; - newStableTokenAddress = stableDebtTokenInstance.address; - }); - - it('Tries to update the DAI Atoken implementation with a different address than the lendingPoolManager', async () => { - const { dai, configurator, users } = testEnv; - - const name = await (await getAToken(newATokenAddress)).name(); - const symbol = await (await getAToken(newATokenAddress)).symbol(); - - const updateATokenInputParams: { - asset: string; - treasury: string; - incentivesController: string; - name: string; - symbol: string; - implementation: string; - } = { - asset: dai.address, - treasury: ZERO_ADDRESS, - incentivesController: ZERO_ADDRESS, - name: name, - symbol: symbol, - implementation: newATokenAddress, - }; - await expect( - configurator.connect(users[1].signer).updateAToken(updateATokenInputParams) - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Upgrades the DAI Atoken implementation ', async () => { - const { dai, configurator, aDai } = testEnv; - - const name = await (await getAToken(newATokenAddress)).name(); - const symbol = await (await getAToken(newATokenAddress)).symbol(); - - const updateATokenInputParams: { - asset: string; - treasury: string; - incentivesController: string; - name: string; - symbol: string; - implementation: string; - } = { - asset: dai.address, - treasury: ZERO_ADDRESS, - incentivesController: ZERO_ADDRESS, - name: name, - symbol: symbol, - implementation: newATokenAddress, - }; - await configurator.updateAToken(updateATokenInputParams); - - const tokenName = await aDai.name(); - - expect(tokenName).to.be.eq('Aave Interest bearing DAI updated', 'Invalid token name'); - }); - - it('Tries to update the DAI Stable debt token implementation with a different address than the lendingPoolManager', async () => { - const { dai, configurator, users } = testEnv; - - const name = await (await getStableDebtToken(newStableTokenAddress)).name(); - const symbol = await (await getStableDebtToken(newStableTokenAddress)).symbol(); - - - const updateDebtTokenInput: { - asset: string; - incentivesController: string; - name: string; - symbol: string; - implementation: string; - } = { - asset: dai.address, - incentivesController: ZERO_ADDRESS, - name: name, - symbol: symbol, - implementation: newStableTokenAddress, - } - - await expect( - configurator - .connect(users[1].signer) - .updateStableDebtToken(updateDebtTokenInput) - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Upgrades the DAI stable debt token implementation ', async () => { - const { dai, configurator, pool, helpersContract } = testEnv; - - const name = await (await getStableDebtToken(newStableTokenAddress)).name(); - const symbol = await (await getStableDebtToken(newStableTokenAddress)).symbol(); - - - const updateDebtTokenInput: { - asset: string; - incentivesController: string; - name: string; - symbol: string; - implementation: string; - } = { - asset: dai.address, - incentivesController: ZERO_ADDRESS, - name: name, - symbol: symbol, - implementation: newStableTokenAddress, - } - - await configurator.updateStableDebtToken(updateDebtTokenInput); - - const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses(dai.address); - - const debtToken = await getMockStableDebtToken(stableDebtTokenAddress); - - const tokenName = await debtToken.name(); - - expect(tokenName).to.be.eq('Aave stable debt bearing DAI updated', 'Invalid token name'); - }); - - it('Tries to update the DAI variable debt token implementation with a different address than the lendingPoolManager', async () => { - const {dai, configurator, users} = testEnv; - - const name = await (await getVariableDebtToken(newVariableTokenAddress)).name(); - const symbol = await (await getVariableDebtToken(newVariableTokenAddress)).symbol(); - - const updateDebtTokenInput: { - asset: string; - incentivesController: string; - name: string; - symbol: string; - implementation: string; - } = { - asset: dai.address, - incentivesController: ZERO_ADDRESS, - name: name, - symbol: symbol, - implementation: newVariableTokenAddress, - } - - await expect( - configurator - .connect(users[1].signer) - .updateVariableDebtToken(updateDebtTokenInput) - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); - }); - - it('Upgrades the DAI variable debt token implementation ', async () => { - const {dai, configurator, pool, helpersContract} = testEnv; - - const name = await (await getVariableDebtToken(newVariableTokenAddress)).name(); - const symbol = await (await getVariableDebtToken(newVariableTokenAddress)).symbol(); - - const updateDebtTokenInput: { - asset: string; - incentivesController: string; - name: string; - symbol: string; - implementation: string; - } = { - asset: dai.address, - incentivesController: ZERO_ADDRESS, - name: name, - symbol: symbol, - implementation: newVariableTokenAddress, - } - //const name = await (await getAToken(newATokenAddress)).name(); - - await configurator.updateVariableDebtToken(updateDebtTokenInput); - - const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - dai.address - ); - - const debtToken = await getMockVariableDebtToken(variableDebtTokenAddress); - - const tokenName = await debtToken.name(); - - expect(tokenName).to.be.eq('Aave variable debt bearing DAI updated', 'Invalid token name'); - }); -}); diff --git a/test/variable-debt-token.spec.ts b/test/variable-debt-token.spec.ts deleted file mode 100644 index 0faf7087..00000000 --- a/test/variable-debt-token.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { expect } from 'chai'; -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { ProtocolErrors, TokenContractId, eContractid } from '../helpers/types'; -import { getVariableDebtToken } from '../helpers/contracts-getters'; - -makeSuite('Variable debt token tests', (testEnv: TestEnv) => { - const { CT_CALLER_MUST_BE_LENDING_POOL } = ProtocolErrors; - - it('Tries to invoke mint not being the LendingPool', async () => { - const { deployer, pool, dai, helpersContract } = testEnv; - - const daiVariableDebtTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).variableDebtTokenAddress; - - const variableDebtContract = await getVariableDebtToken(daiVariableDebtTokenAddress); - - await expect( - variableDebtContract.mint(deployer.address, deployer.address, '1', '1') - ).to.be.revertedWith(CT_CALLER_MUST_BE_LENDING_POOL); - }); - - it('Tries to invoke burn not being the LendingPool', async () => { - const { deployer, pool, dai, helpersContract } = testEnv; - - const daiVariableDebtTokenAddress = ( - await helpersContract.getReserveTokensAddresses(dai.address) - ).variableDebtTokenAddress; - - const variableDebtContract = await getVariableDebtToken(daiVariableDebtTokenAddress); - - await expect(variableDebtContract.burn(deployer.address, '1', '1')).to.be.revertedWith( - CT_CALLER_MUST_BE_LENDING_POOL - ); - }); -}); diff --git a/test/weth-gateway.spec.ts b/test/weth-gateway.spec.ts deleted file mode 100644 index eadf9703..00000000 --- a/test/weth-gateway.spec.ts +++ /dev/null @@ -1,370 +0,0 @@ -import { MAX_UINT_AMOUNT } from '../helpers/constants'; -import { convertToCurrencyDecimals } from '../helpers/contracts-helpers'; -import { makeSuite, TestEnv } from './helpers/make-suite'; -import { parseEther } from 'ethers/lib/utils'; -import { DRE, waitForTx } from '../helpers/misc-utils'; -import { BigNumber } from 'ethers'; -import { getStableDebtToken, getVariableDebtToken } from '../helpers/contracts-getters'; -import { deploySelfdestructTransferMock } from '../helpers/contracts-deployments'; - -const { expect } = require('chai'); - -makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => { - const zero = BigNumber.from('0'); - const depositSize = parseEther('5'); - const daiSize = parseEther('10000'); - it('Deposit WETH via WethGateway and DAI', async () => { - const { users, wethGateway, aWETH } = testEnv; - - const user = users[1]; - const depositor = users[0]; - - // Deposit liquidity with native ETH - await wethGateway - .connect(depositor.signer) - .depositETH(depositor.address, '0', { value: depositSize }); - - // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); - - const aTokensBalance = await aWETH.balanceOf(user.address); - - expect(aTokensBalance).to.be.gt(zero); - expect(aTokensBalance).to.be.gte(depositSize); - }); - - it('Withdraw WETH - Partial', async () => { - const { users, wethGateway, aWETH, pool } = testEnv; - - const user = users[1]; - const priorEthersBalance = await user.signer.getBalance(); - const aTokensBalance = await aWETH.balanceOf(user.address); - - expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.'); - - // Partially withdraw native ETH - const partialWithdraw = await convertToCurrencyDecimals(aWETH.address, '2'); - - // Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether - const approveTx = await aWETH - .connect(user.signer) - .approve(wethGateway.address, MAX_UINT_AMOUNT); - const { gasUsed: approveGas } = await waitForTx(approveTx); - - // Partial Withdraw and send native Ether to user - const { gasUsed: withdrawGas } = await waitForTx( - await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) - ); - - const afterPartialEtherBalance = await user.signer.getBalance(); - const afterPartialATokensBalance = await aWETH.balanceOf(user.address); - const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice); - - expect(afterPartialEtherBalance).to.be.equal( - priorEthersBalance.add(partialWithdraw).sub(gasCosts), - 'User ETHER balance should contain the partial withdraw' - ); - expect(afterPartialATokensBalance).to.be.equal( - aTokensBalance.sub(partialWithdraw), - 'User aWETH balance should be substracted' - ); - }); - - it('Withdraw WETH - Full', async () => { - const { users, aWETH, wethGateway, pool } = testEnv; - - const user = users[1]; - const priorEthersBalance = await user.signer.getBalance(); - const aTokensBalance = await aWETH.balanceOf(user.address); - - expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.'); - - // Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether - const approveTx = await aWETH - .connect(user.signer) - .approve(wethGateway.address, MAX_UINT_AMOUNT); - const { gasUsed: approveGas } = await waitForTx(approveTx); - - // Full withdraw - const { gasUsed: withdrawGas } = await waitForTx( - await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) - ); - - const afterFullEtherBalance = await user.signer.getBalance(); - const afterFullATokensBalance = await aWETH.balanceOf(user.address); - const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice); - - expect(afterFullEtherBalance).to.be.eq( - priorEthersBalance.add(aTokensBalance).sub(gasCosts), - 'User ETHER balance should contain the full withdraw' - ); - expect(afterFullATokensBalance).to.be.eq(0, 'User aWETH balance should be zero'); - }); - - it('Borrow stable WETH and Full Repay with ETH', async () => { - const { users, wethGateway, aDai, weth, dai, pool, helpersContract } = testEnv; - const borrowSize = parseEther('1'); - const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); - const user = users[1]; - const depositor = users[0]; - - // Deposit with native ETH - await wethGateway - .connect(depositor.signer) - .depositETH(depositor.address, '0', { value: depositSize }); - - const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - weth.address - ); - - const stableDebtToken = await getStableDebtToken(stableDebtTokenAddress); - - // Deposit 10000 DAI - await dai.connect(user.signer).mint(daiSize); - await dai.connect(user.signer).approve(pool.address, daiSize); - await pool.connect(user.signer).deposit(dai.address, daiSize, user.address, '0'); - - const aTokensBalance = await aDai.balanceOf(user.address); - - expect(aTokensBalance).to.be.gt(zero); - expect(aTokensBalance).to.be.gte(daiSize); - - // Borrow WETH with WETH as collateral - await waitForTx( - await pool.connect(user.signer).borrow(weth.address, borrowSize, '1', '0', user.address) - ); - - const debtBalance = await stableDebtToken.balanceOf(user.address); - - expect(debtBalance).to.be.gt(zero); - - // Full Repay WETH with native ETH - await waitForTx( - await wethGateway - .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) - ); - - const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); - expect(debtBalanceAfterRepay).to.be.eq(zero); - - // Withdraw DAI - await aDai.connect(user.signer).approve(pool.address, MAX_UINT_AMOUNT); - await pool.connect(user.signer).withdraw(dai.address, MAX_UINT_AMOUNT, user.address); - }); - - it('Borrow variable WETH and Full Repay with ETH', async () => { - const { users, wethGateway, aWETH, weth, pool, helpersContract } = testEnv; - const borrowSize = parseEther('1'); - const repaySize = borrowSize.add(borrowSize.mul(5).div(100)); - const user = users[1]; - - const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - weth.address - ); - - const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); - - // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); - - const aTokensBalance = await aWETH.balanceOf(user.address); - - expect(aTokensBalance).to.be.gt(zero); - expect(aTokensBalance).to.be.gte(depositSize); - - // Borrow WETH with WETH as collateral - await waitForTx( - await pool.connect(user.signer).borrow(weth.address, borrowSize, '2', '0', user.address) - ); - - const debtBalance = await varDebtToken.balanceOf(user.address); - - expect(debtBalance).to.be.gt(zero); - - // Partial Repay WETH loan with native ETH - const partialPayment = repaySize.div(2); - await waitForTx( - await wethGateway - .connect(user.signer) - .repayETH(partialPayment, '2', user.address, { value: partialPayment }) - ); - - const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); - expect(debtBalanceAfterPartialRepay).to.be.lt(debtBalance); - - // Full Repay WETH loan with native ETH - await waitForTx( - await wethGateway - .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) - ); - const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); - expect(debtBalanceAfterFullRepay).to.be.eq(zero); - }); - - it('Borrow ETH via delegateApprove ETH and repays back', async () => { - const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; - const borrowSize = parseEther('1'); - const user = users[2]; - const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - weth.address - ); - const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); - - const priorDebtBalance = await varDebtToken.balanceOf(user.address); - expect(priorDebtBalance).to.be.eq(zero); - - // Deposit WETH with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); - - const aTokensBalance = await aWETH.balanceOf(user.address); - - expect(aTokensBalance).to.be.gt(zero); - expect(aTokensBalance).to.be.gte(depositSize); - - // Delegates borrowing power of WETH to WETHGateway - await waitForTx( - await varDebtToken.connect(user.signer).approveDelegation(wethGateway.address, borrowSize) - ); - - // Borrows ETH with WETH as collateral - await waitForTx(await wethGateway.connect(user.signer).borrowETH(borrowSize, '2', '0')); - - const debtBalance = await varDebtToken.balanceOf(user.address); - - expect(debtBalance).to.be.gt(zero); - - // Full Repay WETH loan with native ETH - await waitForTx( - await wethGateway - .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) - ); - const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); - expect(debtBalanceAfterFullRepay).to.be.eq(zero); - }); - - it('Should revert if receiver function receives Ether if not WETH', async () => { - const { users, wethGateway } = testEnv; - const user = users[0]; - const amount = parseEther('1'); - - // Call receiver function (empty data + value) - await expect( - user.signer.sendTransaction({ - to: wethGateway.address, - value: amount, - gasLimit: DRE.network.config.gas, - }) - ).to.be.revertedWith('Receive not allowed'); - }); - - it('Should revert if fallback functions is called with Ether', async () => { - const { users, wethGateway } = testEnv; - const user = users[0]; - const amount = parseEther('1'); - const fakeABI = ['function wantToCallFallback()']; - const abiCoder = new DRE.ethers.utils.Interface(fakeABI); - const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []); - - // Call fallback function with value - await expect( - user.signer.sendTransaction({ - to: wethGateway.address, - data: fakeMethodEncoded, - value: amount, - gasLimit: DRE.network.config.gas, - }) - ).to.be.revertedWith('Fallback not allowed'); - }); - - it('Should revert if fallback functions is called', async () => { - const { users, wethGateway } = testEnv; - const user = users[0]; - - const fakeABI = ['function wantToCallFallback()']; - const abiCoder = new DRE.ethers.utils.Interface(fakeABI); - const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []); - - // Call fallback function without value - await expect( - user.signer.sendTransaction({ - to: wethGateway.address, - data: fakeMethodEncoded, - gasLimit: DRE.network.config.gas, - }) - ).to.be.revertedWith('Fallback not allowed'); - }); - - it('Getters should retrieve correct state', async () => { - const { aWETH, weth, pool, wethGateway } = testEnv; - - const WETHAddress = await wethGateway.getWETHAddress(); - const aWETHAddress = await wethGateway.getAWETHAddress(); - const poolAddress = await wethGateway.getLendingPoolAddress(); - - expect(WETHAddress).to.be.equal(weth.address); - expect(aWETHAddress).to.be.equal(aWETH.address); - expect(poolAddress).to.be.equal(pool.address); - }); - - it('Owner can do emergency token recovery', async () => { - const { users, dai, wethGateway, deployer } = testEnv; - const user = users[0]; - const amount = parseEther('1'); - - await dai.connect(user.signer).mint(amount); - const daiBalanceAfterMint = await dai.balanceOf(user.address); - - await dai.connect(user.signer).transfer(wethGateway.address, amount); - const daiBalanceAfterBadTransfer = await dai.balanceOf(user.address); - expect(daiBalanceAfterBadTransfer).to.be.eq( - daiBalanceAfterMint.sub(amount), - 'User should have lost the funds here.' - ); - - await wethGateway - .connect(deployer.signer) - .emergencyTokenTransfer(dai.address, user.address, amount); - const daiBalanceAfterRecovery = await dai.balanceOf(user.address); - - expect(daiBalanceAfterRecovery).to.be.eq( - daiBalanceAfterMint, - 'User should recover the funds due emergency token transfer' - ); - }); - - it('Owner can do emergency native ETH recovery', async () => { - const { users, wethGateway, deployer } = testEnv; - const user = users[0]; - const amount = parseEther('1'); - const userBalancePriorCall = await user.signer.getBalance(); - - // Deploy contract with payable selfdestruct contract - const selfdestructContract = await deploySelfdestructTransferMock(); - - // Selfdestruct the mock, pointing to WETHGateway address - const callTx = await selfdestructContract - .connect(user.signer) - .destroyAndTransfer(wethGateway.address, { value: amount }); - const { gasUsed } = await waitForTx(callTx); - const gasFees = gasUsed.mul(callTx.gasPrice); - const userBalanceAfterCall = await user.signer.getBalance(); - - expect(userBalanceAfterCall).to.be.eq(userBalancePriorCall.sub(amount).sub(gasFees), ''); - ('User should have lost the funds'); - - // Recover the funds from the contract and sends back to the user - await wethGateway.connect(deployer.signer).emergencyEtherTransfer(user.address, amount); - - const userBalanceAfterRecovery = await user.signer.getBalance(); - const wethGatewayAfterRecovery = await DRE.ethers.provider.getBalance(wethGateway.address); - - expect(userBalanceAfterRecovery).to.be.eq( - userBalancePriorCall.sub(gasFees), - 'User should recover the funds due emergency eth transfer.' - ); - expect(wethGatewayAfterRecovery).to.be.eq('0', 'WETHGateway ether balance should be zero.'); - }); -}); From 0652b09ffd2fc44500cd519e53a5e07d32dab7f8 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 10 Feb 2021 19:11:41 -0500 Subject: [PATCH 095/219] Slight fixes for tests to run and removed old gas tracker --- helpers/gas-tracker.ts | 10 ---------- tasks/full/1_address_provider.ts | 5 ----- tasks/full/3_oracles.ts | 3 --- tasks/full/5_initialize.ts | 2 -- tasks/migrations/aave.mainnet.ts | 2 -- tasks/migrations/lp.mainnet.ts | 4 ---- test-suites/test-aave/scenario.spec.ts | 2 +- test-suites/test-lp/scenario.spec.ts | 2 +- 8 files changed, 2 insertions(+), 28 deletions(-) delete mode 100644 helpers/gas-tracker.ts diff --git a/helpers/gas-tracker.ts b/helpers/gas-tracker.ts deleted file mode 100644 index 0e165a00..00000000 --- a/helpers/gas-tracker.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @dev This is a simple script that keeps track of gas spent during deployment. - */ -import { BigNumber } from 'ethers'; - -export var totalGas:BigNumber = BigNumber.from(0); - -export function addGas(amount: BigNumber) { - totalGas = totalGas.add(amount); -} \ No newline at end of file diff --git a/tasks/full/1_address_provider.ts b/tasks/full/1_address_provider.ts index 08cc7ea0..ae5fabc0 100644 --- a/tasks/full/1_address_provider.ts +++ b/tasks/full/1_address_provider.ts @@ -20,7 +20,6 @@ import { formatEther, isAddress, parseEther } from 'ethers/lib/utils'; import { isZeroAddress } from 'ethereumjs-util'; import { Signer, BigNumber } from 'ethers'; import { parse } from 'path'; -import { addGas } from '../../helpers/gas-tracker'; //import BigNumber from 'bignumber.js'; task( @@ -95,10 +94,6 @@ task( // 4. Set pool admins - - addGas(await addressesProvider.estimateGas.setPoolAdmin(await getGenesisPoolAdmin(poolConfig))); - addGas(await addressesProvider.estimateGas.setEmergencyAdmin(await getEmergencyAdmin(poolConfig))); - await waitForTx(await addressesProvider.setPoolAdmin(await getGenesisPoolAdmin(poolConfig))); await waitForTx(await addressesProvider.setEmergencyAdmin(await getEmergencyAdmin(poolConfig))); diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index ce830b8c..3c37eb74 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -17,7 +17,6 @@ import { getLendingRateOracle, getPairsTokenAggregator, } from '../../helpers/contracts-getters'; -import { addGas } from '../../helpers/gas-tracker'; task('full:deploy-oracles', 'Deploy oracles for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') @@ -69,8 +68,6 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') } console.log("ORACLES: %s and %s", aaveOracle.address, lendingRateOracle.address); // Register the proxy price provider on the addressesProvider - addGas(await addressesProvider.estimateGas.setPriceOracle(aaveOracle.address)); - addGas(await addressesProvider.estimateGas.setLendingRateOracle(lendingRateOracle.address)); await waitForTx(await addressesProvider.setPriceOracle(aaveOracle.address)); await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); } catch (error) { diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 813a6a3e..9999f6f1 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -21,7 +21,6 @@ import { getLendingPoolAddressesProvider, } from '../../helpers/contracts-getters'; import { ZERO_ADDRESS } from '../../helpers/constants'; -import { addGas } from '../../helpers/gas-tracker'; task('full:initialize-lending-pool', 'Initialize lending pool configuration.') .addFlag('verify', 'Verify contracts at Etherscan') @@ -58,7 +57,6 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const collateralManager = await deployLendingPoolCollateralManager(verify); - addGas(await addressesProvider.estimateGas.setLendingPoolCollateralManager(collateralManager.address)); await waitForTx( await addressesProvider.setLendingPoolCollateralManager(collateralManager.address) ); diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index a987451c..96bcbbb8 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -3,7 +3,6 @@ import { checkVerification } from '../../helpers/etherscan-verification'; import { ConfigNames } from '../../helpers/configuration'; import { printContracts } from '../../helpers/misc-utils'; import { usingTenderly } from '../../helpers/tenderly-utils'; -import {totalGas} from '../../helpers/gas-tracker'; task('aave:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') @@ -48,5 +47,4 @@ task('aave:mainnet', 'Deploy development enviroment') } console.log('\nFinished migrations'); printContracts(); - console.log("Total gas used:", totalGas.toString()); }); diff --git a/tasks/migrations/lp.mainnet.ts b/tasks/migrations/lp.mainnet.ts index 9b23a499..70121c03 100644 --- a/tasks/migrations/lp.mainnet.ts +++ b/tasks/migrations/lp.mainnet.ts @@ -4,7 +4,6 @@ import {checkVerification} from '../../helpers/etherscan-verification'; import {ConfigNames} from '../../helpers/configuration'; import {EthereumNetworkNames} from '../../helpers/types'; import {printContracts} from '../../helpers/misc-utils'; -import {totalGas} from '../../helpers/gas-tracker'; task('lp:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') @@ -24,8 +23,6 @@ task('lp:mainnet', 'Deploy development enviroment') const provider = new DRE.ethers.providers.Web3Provider(DRE.tenderlyRPC as any); DRE.ethers.provider = provider; } - // addGas(1); - // console.log(totalGas); console.log('Migration started\n'); @@ -59,5 +56,4 @@ task('lp:mainnet', 'Deploy development enviroment') } console.log('\nFinished migrations'); printContracts(); - console.log("Total gas used:", totalGas.toString()); }); diff --git a/test-suites/test-aave/scenario.spec.ts b/test-suites/test-aave/scenario.spec.ts index 55f02cad..68b792d5 100644 --- a/test-suites/test-aave/scenario.spec.ts +++ b/test-suites/test-aave/scenario.spec.ts @@ -8,7 +8,7 @@ import { getReservesConfigByPool } from '../../helpers/configuration'; import { AavePools, iAavePoolAssets, IReserveParams } from '../../helpers/types'; import { executeStory } from './helpers/scenario-engine'; -const scenarioFolder = './test/helpers/scenarios/'; +const scenarioFolder = './test-suites/test-aave/helpers/scenarios/'; const selectedScenarios: string[] = []; diff --git a/test-suites/test-lp/scenario.spec.ts b/test-suites/test-lp/scenario.spec.ts index 076ae9db..99bed044 100644 --- a/test-suites/test-lp/scenario.spec.ts +++ b/test-suites/test-lp/scenario.spec.ts @@ -8,7 +8,7 @@ import { getReservesConfigByPool } from '../../helpers/configuration'; import { AavePools, iLpPoolAssets, IReserveParams } from '../../helpers/types'; import { executeStory } from './helpers/scenario-engine'; -const scenarioFolder = './test/helpers/scenarios/'; +const scenarioFolder = './test-suites/test-lp/helpers/scenarios/'; const selectedScenarios: string[] = []; From 9a9f4183a6ff961dea348fc4f9641c8a1d34c1d5 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 11 Feb 2021 22:25:37 -0500 Subject: [PATCH 096/219] Changed to more recent forked block --- hardhat.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index a6d411ea..935aa371 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -65,7 +65,7 @@ const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number const mainnetFork = MAINNET_FORK ? { - blockNumber: 11608298, + blockNumber: 11739065, url: ALCHEMY_KEY ? `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}` : `https://mainnet.infura.io/v3/${INFURA_KEY}`, From 5cc18fe6f3138a160d439ddf1daddab74b6d63f8 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 11 Feb 2021 22:50:46 -0500 Subject: [PATCH 097/219] Added kovan assets --- markets/lp/index.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/markets/lp/index.ts b/markets/lp/index.ts index 55d44e86..af9b1971 100644 --- a/markets/lp/index.ts +++ b/markets/lp/index.ts @@ -63,9 +63,20 @@ export const lpConfig: ILpConfiguration = { LpUSDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', LpWBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', LpWETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', - LpDAIWETH: '0x7d3A67ab574abD3F9849e5fcDa48c19939d032b4', - uniWBTCWETH: '0x342e78bf229Cd2a750E80D7D7c2C185455979b91', - // Other assets + LpDAIWETH: '0x7e48b02B21D784e79E17b06988fc150c8b5945df', + LpWBTCWETH: '0x4Fd18882730dc5f945d5049C3f99Ee43CCA1F3d9', + LpAAVEWETH: '0xC173038224d47e11962bb0Bd10e036c573C57dF0', + LpBATWETH: '0xfC482c56A91Cc92019FF6522B2FB76F41B7e2535', + LpUSDCDAI: '0xFD0795980D4c37Fd867228C86A1f7693C9219142', + LpCRVWETH: '0xC7f1899F8B5861d8A3Ce1385194bc130A15C8a74', + LpLINKWETH: '0xCe2355F9249ced9E51ecc35AbB749352C2557D0d', + LpMKRWETH: '0xDCf7A28f4102B7f5813148cCEFb02134648E6F0C', + LpRENWETH: '0xe46C9459833bBa061471DF2a383D27a20FE97E23', + LpSNXWETH: '0xAa5826dea7cfEc02AcB644b24387bE2648feAbB9', + LpUNIWETH: '0xD4C255B5500cFB262EB5F9105Ea546Aa0610A0d3', + LpUSDCWETH: '0x509f6ce2F9718E3dd854cCE1857FabCc59C6dd5e', + LpWBTCUSDC: '0x9D15e3A14926A16C9B285A5c6bd6c9e82d5F8031', + LpYFIWETH: '0xC6Dc783B3C2E2Cbf71791d253f8b4993D40DBf98', }, [EthereumNetwork.ropsten]: { }, From 283cf2ce97ed16532728f2d17b30a473bcd4752b Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 11 Feb 2021 22:54:04 -0500 Subject: [PATCH 098/219] Added re-using collateral manager functionality --- helpers/types.ts | 1 + markets/aave/commons.ts | 9 ++++++++ markets/lp/commons.ts | 45 +++++++++++++++++++++++--------------- tasks/full/5_initialize.ts | 14 ++++++++---- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/helpers/types.ts b/helpers/types.ts index b6c9195f..64d98b74 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -430,6 +430,7 @@ export interface ICommonConfiguration { Mocks: IMocksConfig; ProviderRegistry: iParamsPerNetwork; ProviderRegistryOwner: iParamsPerNetwork; + LendingPoolCollateralManager: iParamsPerNetwork; LendingRateOracleRatesCommon: iMultiPoolsAssets; LendingRateOracle: iParamsPerNetwork; TokenDistributor: iParamsPerNetwork; diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index 69d820ab..5234feff 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -182,6 +182,15 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', [eEthereumNetwork.main]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', + }, + LendingPoolCollateralManager: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '0x9269b6453d0d75370c4c85e5a42977a53efdb72a', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', + [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', }, TokenDistributor: { [eEthereumNetwork.coverage]: '', diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index aaca1cf0..53b0904b 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -177,11 +177,20 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '',//'0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', + [eEthereumNetwork.kovan]: '0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', - [eEthereumNetwork.main]: '', //'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', + [eEthereumNetwork.main]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', }, + LendingPoolCollateralManager: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '0x9269b6453d0d75370c4c85e5a42977a53efdb72a', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', + [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', + }, TokenDistributor: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.buidlerevm]: '', @@ -195,9 +204,9 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [EthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', + [EthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', // Need to re-deploy because of onlyOwner [EthereumNetwork.ropsten]: ZERO_ADDRESS, - [EthereumNetwork.main]: '', //'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', + [EthereumNetwork.main]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', }, FallbackOracle: { @@ -218,20 +227,20 @@ export const CommonsConfig: ICommonConfiguration = { LpWBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', LpUSDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', LpDAI:'0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', - LpDAIWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', // Mock oracles - LpWBTCWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - LpAAVEWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - LpBATWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - LpUSDCDAI: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - LpCRVWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - LpLINKWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - LpMKRWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - LpRENWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - LpSNXWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - LpUNIWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - LpUSDCWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - LpWBTCUSDC: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', - LpYFIWETH: '0x90B86B501BF4d800a7F76E551952E214Cc58Fba3', + LpDAIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', // Mock oracles + LpWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpAAVEWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpBATWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUSDCDAI: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpCRVWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpLINKWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpMKRWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpRENWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpSNXWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUNIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUSDCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpWBTCUSDC: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpYFIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [EthereumNetwork.ropsten]: { diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 9999f6f1..a8e93f7e 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -3,7 +3,6 @@ import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { deployLendingPoolCollateralManager, deployWalletBalancerProvider, - deployAaveProtocolDataProvider, deployWETHGateway, } from '../../helpers/contracts-deployments'; import { @@ -30,7 +29,7 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') await localBRE.run('set-DRE'); const network = localBRE.network.name; const poolConfig = loadPoolConfig(pool); - const { ReserveAssets, ReservesConfig } = poolConfig as ICommonConfiguration; + const { ReserveAssets, ReservesConfig, LendingPoolCollateralManager } = poolConfig as ICommonConfiguration; const reserveAssets = await getParamPerNetwork(ReserveAssets, network); @@ -55,10 +54,17 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') ); await configureReservesByHelper(ReservesConfig, reserveAssets, testHelpers, admin); - const collateralManager = await deployLendingPoolCollateralManager(verify); + + + let collateralManagerAddress = await getParamPerNetwork(LendingPoolCollateralManager, network); + if (!collateralManagerAddress) { + const collateralManager = await deployLendingPoolCollateralManager(verify); + collateralManagerAddress = collateralManager.address; + } + // Seems unnecessary to register the collateral manager in the JSON db await waitForTx( - await addressesProvider.setLendingPoolCollateralManager(collateralManager.address) + await addressesProvider.setLendingPoolCollateralManager(collateralManagerAddress) ); await deployWalletBalancerProvider(verify); From 313e3146f41db13cd06406e003ebb5a6d64f82c3 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 12 Feb 2021 11:08:36 -0500 Subject: [PATCH 099/219] Added functionality to re-use Aave/Lending Rate Oracles --- markets/lp/commons.ts | 6 +++--- tasks/full/3_oracles.ts | 43 +++++++++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index 53b0904b..736e3a96 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -177,9 +177,9 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', + [eEthereumNetwork.kovan]: '', //'0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', // Need to re-deploy because of onlyOwner [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', - [eEthereumNetwork.main]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', + [eEthereumNetwork.main]: '', //'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', // Need to re-deploy because of onlyOwner [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', }, LendingPoolCollateralManager: { @@ -206,7 +206,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.buidlerevm]: '', [EthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', // Need to re-deploy because of onlyOwner [EthereumNetwork.ropsten]: ZERO_ADDRESS, - [EthereumNetwork.main]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', + [EthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', // Need to re-deploy because of onlyOwner [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', }, FallbackOracle: { diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index 3c37eb74..382eb380 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -1,7 +1,7 @@ import { task } from 'hardhat/config'; import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { deployAaveOracle, deployLendingRateOracle } from '../../helpers/contracts-deployments'; -import { setInitialMarketRatesInRatesOracleByHelper } from '../../helpers/oracles-helpers'; +import { setInitialAssetPricesInOracle, setInitialMarketRatesInRatesOracleByHelper } from '../../helpers/oracles-helpers'; import { ICommonConfiguration, eEthereumNetwork, SymbolMap } from '../../helpers/types'; import { waitForTx, notFalsyOrZeroAddress } from '../../helpers/misc-utils'; import { @@ -17,6 +17,7 @@ import { getLendingRateOracle, getPairsTokenAggregator, } from '../../helpers/contracts-getters'; +import { AaveOracle } from '../../types'; task('full:deploy-oracles', 'Deploy oracles for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') @@ -47,25 +48,37 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') }; const [tokens, aggregators] = getPairsTokenAggregator(tokensToWatch, chainlinkAggregators); - const aaveOracle = notFalsyOrZeroAddress(aaveOracleAddress) - ? await getAaveOracle(aaveOracleAddress) - : await deployAaveOracle( - [tokens, aggregators, fallbackOracleAddress, await getWethAddress(poolConfig)], - verify - ); + // const aaveOracle = notFalsyOrZeroAddress(aaveOracleAddress) + // ? await getAaveOracle(aaveOracleAddress) + // : await deployAaveOracle( + // [tokens, aggregators, fallbackOracleAddress, await getWethAddress(poolConfig)], + // verify + // ); + + let aaveOracle: AaveOracle; + if (notFalsyOrZeroAddress(aaveOracleAddress)) { + aaveOracle = await getAaveOracle(aaveOracleAddress); + await aaveOracle.setAssetSources(tokens, aggregators); + } else { + aaveOracle = await deployAaveOracle( + [tokens, aggregators, fallbackOracleAddress, await getWethAddress(poolConfig)], + verify + ); + } const lendingRateOracle = notFalsyOrZeroAddress(lendingRateOracleAddress) ? await getLendingRateOracle(lendingRateOracleAddress) : await deployLendingRateOracle(verify); const { USD, ...tokensAddressesWithoutUsd } = tokensToWatch; - if (!lendingRateOracleAddress) { - await setInitialMarketRatesInRatesOracleByHelper( - lendingRateOracles, - tokensAddressesWithoutUsd, - lendingRateOracle, - admin - ); - } + // This must be done any time a new market is created I believe + //if (!lendingRateOracleAddress) { + await setInitialMarketRatesInRatesOracleByHelper( + lendingRateOracles, + tokensAddressesWithoutUsd, + lendingRateOracle, + admin + ); + //} console.log("ORACLES: %s and %s", aaveOracle.address, lendingRateOracle.address); // Register the proxy price provider on the addressesProvider await waitForTx(await addressesProvider.setPriceOracle(aaveOracle.address)); From 0c2b92a0c8d2e81ba11366d3e55f2aff20b56509 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 12 Feb 2021 21:40:20 -0500 Subject: [PATCH 100/219] Removed useless import --- tasks/full/3_oracles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index 382eb380..677681ec 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -1,7 +1,7 @@ import { task } from 'hardhat/config'; import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { deployAaveOracle, deployLendingRateOracle } from '../../helpers/contracts-deployments'; -import { setInitialAssetPricesInOracle, setInitialMarketRatesInRatesOracleByHelper } from '../../helpers/oracles-helpers'; +import { setInitialMarketRatesInRatesOracleByHelper } from '../../helpers/oracles-helpers'; import { ICommonConfiguration, eEthereumNetwork, SymbolMap } from '../../helpers/types'; import { waitForTx, notFalsyOrZeroAddress } from '../../helpers/misc-utils'; import { From 32e425fe1784ef3591019a3997af38b6473e2dcf Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 12 Feb 2021 21:40:39 -0500 Subject: [PATCH 101/219] Commented oracles to allow for deployment from a non-owner --- markets/aave/commons.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index 5234feff..36658744 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -178,9 +178,9 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', + [eEthereumNetwork.kovan]: '',//'0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', - [eEthereumNetwork.main]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', + [eEthereumNetwork.main]: '',//'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', }, LendingPoolCollateralManager: { @@ -205,9 +205,9 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [EthereumNetwork.kovan]: '0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', + [EthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', [EthereumNetwork.ropsten]: ZERO_ADDRESS, - [EthereumNetwork.main]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', + [EthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', }, FallbackOracle: { From e72c07ae6d8990864d73293c856722ab8d906d20 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 12 Feb 2021 21:49:53 -0500 Subject: [PATCH 102/219] Cleanup & added a comment for clarity on a potentially deprecated function. --- helpers/init-helpers.ts | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 4664bb23..c7bf84b9 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -51,13 +51,8 @@ export const initReservesByHelper = async ( ): Promise => { let gasUsage = BigNumber.from('0'); 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)); // CHUNK CONFIGURATION const initChunks = 4; @@ -85,7 +80,6 @@ export const initReservesByHelper = async ( stableDebtTokenSymbol: string, }[] = []; - //let lastStrategy: string = ""; let strategyRates: [ string, // addresses provider string, @@ -227,9 +221,6 @@ export const initReservesByHelper = async ( //gasUsage = gasUsage.add(tx3.gasUsed); } - - // Set deployer back as admin - await waitForTx(await addressProvider.setPoolAdmin(admin)); return gasUsage; // Deprecated }; @@ -360,6 +351,9 @@ const getAddressById = async ( ): Promise => (await getDb().get(`${id}.${network}`).value())?.address || undefined; +// Function deprecated? Updated but untested, script is not updated on package.json. +// This is not called during regular deployment, only in the "full:initialize-tokens" +// hardhat task. export const initTokenReservesByHelper = async ( reservesParams: iMultiPoolsAssets, tokenAddresses: { [symbol: string]: tEthereumAddress }, From f196a3be7ab5699e79427d2ba5a52f695ea40c70 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 15 Feb 2021 22:50:16 -0500 Subject: [PATCH 103/219] Added Balancer WBTCWETH. Renamed tokens to show underlying AMM. --- helpers/types.ts | 87 ++++++----- markets/aave/commons.ts | 29 ++-- markets/lp/commons.ts | 147 +++++++++--------- markets/lp/index.ts | 112 +++++++------ test-suites/test-aave/__setup.spec.ts | 29 ++-- test-suites/test-lp/__setup.spec.ts | 29 ++-- test-suites/test-lp/helpers/make-suite.ts | 2 +- .../scenarios/borrow-repay-variable.json | 10 +- .../scenarios/set-use-as-collateral.json | 18 +-- 9 files changed, 247 insertions(+), 216 deletions(-) diff --git a/helpers/types.ts b/helpers/types.ts index 64d98b74..54c75180 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -210,20 +210,21 @@ export interface iAssetBase { LpDAI: T; LpUSDC: T; LpUSDT: T; - LpDAIWETH: T; - LpWBTCWETH: T; - LpAAVEWETH: T; - LpBATWETH: T; - LpUSDCDAI: T; - LpCRVWETH: T; - LpLINKWETH: T; - LpMKRWETH: T; - LpRENWETH: T; - LpSNXWETH: T; - LpUNIWETH: T; - LpUSDCWETH: T; - LpWBTCUSDC: T; - LpYFIWETH: T; + LpUniDAIWETH: T; + LpUniWBTCWETH: T; + LpUniAAVEWETH: T; + LpUniBATWETH: T; + LpUniUSDCDAI: T; + LpUniCRVWETH: T; + LpUniLINKWETH: T; + LpUniMKRWETH: T; + LpUniRENWETH: T; + LpUniSNXWETH: T; + LpUniUNIWETH: T; + LpUniUSDCWETH: T; + LpUniWBTCUSDC: T; + LpUniYFIWETH: T; + LpBalWBTCWETH: T; } export type iAssetsWithoutETH = Omit, 'ETH'>; @@ -261,20 +262,21 @@ export type iLpPoolAssets = Pick< | 'LpUSDT' | 'LpWBTC' | 'LpWETH' - | 'LpDAIWETH' - | 'LpWBTCWETH' - | 'LpAAVEWETH' - | 'LpBATWETH' - | 'LpUSDCDAI' - | 'LpCRVWETH' - | 'LpLINKWETH' - | 'LpMKRWETH' - | 'LpRENWETH' - | 'LpSNXWETH' - | 'LpUNIWETH' - | 'LpUSDCWETH' - | 'LpWBTCUSDC' - | 'LpYFIWETH' + | 'LpUniDAIWETH' + | 'LpUniWBTCWETH' + | 'LpUniAAVEWETH' + | 'LpUniBATWETH' + | 'LpUniUSDCDAI' + | 'LpUniCRVWETH' + | 'LpUniLINKWETH' + | 'LpUniMKRWETH' + | 'LpUniRENWETH' + | 'LpUniSNXWETH' + | 'LpUniUNIWETH' + | 'LpUniUSDCWETH' + | 'LpUniWBTCUSDC' + | 'LpUniYFIWETH' + | 'LpBalWBTCWETH' >; export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; @@ -310,20 +312,21 @@ export enum TokenContractId { LpDAI = 'LpDAI', LpUSDC = 'LpUSDC', LpUSDT = 'LpUSDT', - LpDAIWETH = 'LpDAIWETH', - LpWBTCWETH = 'LpWBTCWETH', - LpAAVEWETH = 'LpAAVEWETH', - LpBATWETH = 'LpBATWETH', - LpUSDCDAI = 'LpUSDCDAI', - LpCRVWETH = 'LpCRVWETH', - LpLINKWETH = 'LpLINKWETH', - LpMKRWETH = 'LpMKRWETH', - LpRENWETH = 'LpRENWETH', - LpSNXWETH = 'LpSNXWETH', - LpUNIWETH = 'LpUNIWETH', - LpUSDCWETH = 'LpUSDCWETH', - LpWBTCUSDC = 'LpWBTCUSDC', - LpYFIWETH = 'LpYFIWETH', + LpUniDAIWETH = 'LpUniDAIWETH', + LpUniWBTCWETH = 'LpUniWBTCWETH', + LpUniAAVEWETH = 'LpUniAAVEWETH', + LpUniBATWETH = 'LpUniBATWETH', + LpUniUSDCDAI = 'LpUniUSDCDAI', + LpUniCRVWETH = 'LpUniCRVWETH', + LpUniLINKWETH = 'LpUniLINKWETH', + LpUniMKRWETH = 'LpUniMKRWETH', + LpUniRENWETH = 'LpUniRENWETH', + LpUniSNXWETH = 'LpUniSNXWETH', + LpUniUNIWETH = 'LpUniUNIWETH', + LpUniUSDCWETH = 'LpUniUSDCWETH', + LpUniWBTCUSDC = 'LpUniWBTCUSDC', + LpUniYFIWETH = 'LpUniYFIWETH', + LpBalWBTCWETH = 'LpBalWBTCWETH', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index 36658744..f5992dba 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -28,20 +28,21 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), LpWETH: oneEther.toFixed(), - LpDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), - LpBATWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), - LpCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), - LpMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpRENWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), - LpYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), + LpUniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), + LpUniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), + LpUniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), + LpUniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpBalWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index 736e3a96..da376b39 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -28,20 +28,21 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), LpWETH: oneEther.toFixed(), - LpDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), - LpBATWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), - LpCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), - LpMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpRENWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), - LpYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), + LpUniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), + LpUniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), + LpUniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), + LpUniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpBalWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; // ---------------- @@ -86,46 +87,49 @@ export const CommonsConfig: ICommonConfiguration = { LpWBTC: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - LpDAIWETH: { + LpUniDAIWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpWBTCWETH: { + LpUniWBTCWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpAAVEWETH:{ + LpUniAAVEWETH:{ borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpBATWETH: { + LpUniBATWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUSDCDAI: { + LpUniUSDCDAI: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpCRVWETH: { + LpUniCRVWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpLINKWETH: { + LpUniLINKWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpMKRWETH: { + LpUniMKRWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpRENWETH: { + LpUniRENWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpSNXWETH: { + LpUniSNXWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUNIWETH: { + LpUniUNIWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUSDCWETH: { + LpUniUSDCWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpWBTCUSDC: { + LpUniWBTCUSDC: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpYFIWETH: { + LpUniYFIWETH: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + LpBalWBTCWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, }, @@ -227,20 +231,21 @@ export const CommonsConfig: ICommonConfiguration = { LpWBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', LpUSDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', LpDAI:'0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', - LpDAIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', // Mock oracles - LpWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpAAVEWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpBATWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUSDCDAI: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpCRVWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpLINKWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpMKRWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpRENWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpSNXWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUNIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUSDCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpWBTCUSDC: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpYFIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniDAIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', // Mock oracles + LpUniWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniAAVEWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniBATWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniUSDCDAI: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniCRVWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniLINKWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniMKRWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniRENWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniSNXWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniUNIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniUSDCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniWBTCUSDC: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpUniYFIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + LpBalWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [EthereumNetwork.ropsten]: { @@ -250,20 +255,21 @@ export const CommonsConfig: ICommonConfiguration = { LpWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', LpUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', LpDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', - LpDAIWETH: '0xf4071801C4421Db7e63DaC15B9432e50C44a7F42', - LpWBTCWETH: ZERO_ADDRESS, - LpAAVEWETH: ZERO_ADDRESS, - LpBATWETH: ZERO_ADDRESS, - LpUSDCDAI: ZERO_ADDRESS, - LpCRVWETH: ZERO_ADDRESS, - LpLINKWETH: ZERO_ADDRESS, - LpMKRWETH: ZERO_ADDRESS, - LpRENWETH: ZERO_ADDRESS, - LpSNXWETH: ZERO_ADDRESS, - LpUNIWETH: ZERO_ADDRESS, - LpUSDCWETH: ZERO_ADDRESS, - LpWBTCUSDC: ZERO_ADDRESS, - LpYFIWETH: ZERO_ADDRESS, + LpUniDAIWETH: '0xf4071801C4421Db7e63DaC15B9432e50C44a7F42', + LpUniWBTCWETH: ZERO_ADDRESS, + LpUniAAVEWETH: ZERO_ADDRESS, + LpUniBATWETH: ZERO_ADDRESS, + LpUniUSDCDAI: ZERO_ADDRESS, + LpUniCRVWETH: ZERO_ADDRESS, + LpUniLINKWETH: ZERO_ADDRESS, + LpUniMKRWETH: ZERO_ADDRESS, + LpUniRENWETH: ZERO_ADDRESS, + LpUniSNXWETH: ZERO_ADDRESS, + LpUniUNIWETH: ZERO_ADDRESS, + LpUniUSDCWETH: ZERO_ADDRESS, + LpUniWBTCUSDC: ZERO_ADDRESS, + LpUniYFIWETH: ZERO_ADDRESS, + LpBalWBTCWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [EthereumNetwork.tenderlyMain]: { @@ -271,20 +277,21 @@ export const CommonsConfig: ICommonConfiguration = { LpWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', LpUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', LpDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', - LpDAIWETH: ZERO_ADDRESS, - LpWBTCWETH: ZERO_ADDRESS, - LpAAVEWETH: ZERO_ADDRESS, - LpBATWETH: ZERO_ADDRESS, - LpUSDCDAI: ZERO_ADDRESS, - LpCRVWETH: ZERO_ADDRESS, - LpLINKWETH: ZERO_ADDRESS, - LpMKRWETH: ZERO_ADDRESS, - LpRENWETH: ZERO_ADDRESS, - LpSNXWETH: ZERO_ADDRESS, - LpUNIWETH: ZERO_ADDRESS, - LpUSDCWETH: ZERO_ADDRESS, - LpWBTCUSDC: ZERO_ADDRESS, - LpYFIWETH: ZERO_ADDRESS, + LpUniDAIWETH: ZERO_ADDRESS, + LpUniWBTCWETH: ZERO_ADDRESS, + LpUniAAVEWETH: ZERO_ADDRESS, + LpUniBATWETH: ZERO_ADDRESS, + LpUniUSDCDAI: ZERO_ADDRESS, + LpUniCRVWETH: ZERO_ADDRESS, + LpUniLINKWETH: ZERO_ADDRESS, + LpUniMKRWETH: ZERO_ADDRESS, + LpUniRENWETH: ZERO_ADDRESS, + LpUniSNXWETH: ZERO_ADDRESS, + LpUniUNIWETH: ZERO_ADDRESS, + LpUniUSDCWETH: ZERO_ADDRESS, + LpUniWBTCUSDC: ZERO_ADDRESS, + LpUniYFIWETH: ZERO_ADDRESS, + LpBalWBTCWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, }, diff --git a/markets/lp/index.ts b/markets/lp/index.ts index af9b1971..c1105a05 100644 --- a/markets/lp/index.ts +++ b/markets/lp/index.ts @@ -38,20 +38,21 @@ export const lpConfig: ILpConfiguration = { LpUSDC: strategyUSDC, LpUSDT: strategyUSDT, LpWBTC: strategyWBTC, - LpDAIWETH: strategyDAIWETH, - LpWBTCWETH: strategyWBTCWETH, - LpAAVEWETH: strategyAAVEWETH, - LpBATWETH: strategyBATWETH, - LpUSDCDAI: strategyUSDCDAI, - LpCRVWETH: strategyCRVWETH, - LpLINKWETH: strategyLINKWETH, - LpMKRWETH: strategyMKRWETH, - LpRENWETH: strategyRENWETH, - LpSNXWETH: strategySNXWETH, - LpUNIWETH: strategyUNIWETH, - LpUSDCWETH: strategyUSDCWETH, - LpWBTCUSDC: strategyWBTCUSDC, - LpYFIWETH: strategyYFIWETH, + LpUniDAIWETH: strategyDAIWETH, + LpUniWBTCWETH: strategyWBTCWETH, + LpUniAAVEWETH: strategyAAVEWETH, + LpUniBATWETH: strategyBATWETH, + LpUniUSDCDAI: strategyUSDCDAI, + LpUniCRVWETH: strategyCRVWETH, + LpUniLINKWETH: strategyLINKWETH, + LpUniMKRWETH: strategyMKRWETH, + LpUniRENWETH: strategyRENWETH, + LpUniSNXWETH: strategySNXWETH, + LpUniUNIWETH: strategyUNIWETH, + LpUniUSDCWETH: strategyUSDCWETH, + LpUniWBTCUSDC: strategyWBTCUSDC, + LpUniYFIWETH: strategyYFIWETH, + LpBalWBTCWETH: strategyWBTCWETH, }, ReserveAssets: { [eEthereumNetwork.buidlerevm]: {}, @@ -63,20 +64,21 @@ export const lpConfig: ILpConfiguration = { LpUSDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', LpWBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', LpWETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', - LpDAIWETH: '0x7e48b02B21D784e79E17b06988fc150c8b5945df', - LpWBTCWETH: '0x4Fd18882730dc5f945d5049C3f99Ee43CCA1F3d9', - LpAAVEWETH: '0xC173038224d47e11962bb0Bd10e036c573C57dF0', - LpBATWETH: '0xfC482c56A91Cc92019FF6522B2FB76F41B7e2535', - LpUSDCDAI: '0xFD0795980D4c37Fd867228C86A1f7693C9219142', - LpCRVWETH: '0xC7f1899F8B5861d8A3Ce1385194bc130A15C8a74', - LpLINKWETH: '0xCe2355F9249ced9E51ecc35AbB749352C2557D0d', - LpMKRWETH: '0xDCf7A28f4102B7f5813148cCEFb02134648E6F0C', - LpRENWETH: '0xe46C9459833bBa061471DF2a383D27a20FE97E23', - LpSNXWETH: '0xAa5826dea7cfEc02AcB644b24387bE2648feAbB9', - LpUNIWETH: '0xD4C255B5500cFB262EB5F9105Ea546Aa0610A0d3', - LpUSDCWETH: '0x509f6ce2F9718E3dd854cCE1857FabCc59C6dd5e', - LpWBTCUSDC: '0x9D15e3A14926A16C9B285A5c6bd6c9e82d5F8031', - LpYFIWETH: '0xC6Dc783B3C2E2Cbf71791d253f8b4993D40DBf98', + LpUniDAIWETH: '0x7e48b02B21D784e79E17b06988fc150c8b5945df', + LpUniWBTCWETH: '0x4Fd18882730dc5f945d5049C3f99Ee43CCA1F3d9', + LpUniAAVEWETH: '0xC173038224d47e11962bb0Bd10e036c573C57dF0', + LpUniBATWETH: '0xfC482c56A91Cc92019FF6522B2FB76F41B7e2535', + LpUniUSDCDAI: '0xFD0795980D4c37Fd867228C86A1f7693C9219142', + LpUniCRVWETH: '0xC7f1899F8B5861d8A3Ce1385194bc130A15C8a74', + LpUniLINKWETH: '0xCe2355F9249ced9E51ecc35AbB749352C2557D0d', + LpUniMKRWETH: '0xDCf7A28f4102B7f5813148cCEFb02134648E6F0C', + LpUniRENWETH: '0xe46C9459833bBa061471DF2a383D27a20FE97E23', + LpUniSNXWETH: '0xAa5826dea7cfEc02AcB644b24387bE2648feAbB9', + LpUniUNIWETH: '0xD4C255B5500cFB262EB5F9105Ea546Aa0610A0d3', + LpUniUSDCWETH: '0x509f6ce2F9718E3dd854cCE1857FabCc59C6dd5e', + LpUniWBTCUSDC: '0x9D15e3A14926A16C9B285A5c6bd6c9e82d5F8031', + LpUniYFIWETH: '0xC6Dc783B3C2E2Cbf71791d253f8b4993D40DBf98', + LpBalWBTCWETH: '0x930087451C5940B28bE556d32a4CF22D5d9754A1', }, [EthereumNetwork.ropsten]: { }, @@ -86,27 +88,43 @@ export const lpConfig: ILpConfiguration = { LpUSDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', LpWBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', LpWETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - LpDAIWETH: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', - LpWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', - LpAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f', - LpBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838', - LpUSDCDAI: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', - LpCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE', - LpLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974', - LpMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225', - LpRENWETH: '0x8Bd1661Da98EBDd3BD080F0bE4e6d9bE8cE9858c', - LpSNXWETH: '0x43AE24960e5534731Fc831386c07755A2dc33D47', - LpUNIWETH: '0xd3d2E2692501A5c9Ca623199D38826e513033a17', - LpUSDCWETH: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc', - LpWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416', - LpYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', + LpUniDAIWETH: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', + LpUniWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', + LpUniAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f', + LpUniBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838', + LpUniUSDCDAI: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', + LpUniCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE', + LpUniLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974', + LpUniMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225', + LpUniRENWETH: '0x8Bd1661Da98EBDd3BD080F0bE4e6d9bE8cE9858c', + LpUniSNXWETH: '0x43AE24960e5534731Fc831386c07755A2dc33D47', + LpUniUNIWETH: '0xd3d2E2692501A5c9Ca623199D38826e513033a17', + LpUniUSDCWETH: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc', + LpUniWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416', + LpUniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', + LpBalWBTCWETH: '0x1efF8aF5D577060BA4ac8A29A13525bb0Ee2A3D5', }, [EthereumNetwork.tenderlyMain]: { - DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', - WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', - WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + LpDAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + LpUSDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + LpUSDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + LpWBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + LpWETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + LpUniDAIWETH: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', + LpUniWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', + LpUniAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f', + LpUniBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838', + LpUniUSDCDAI: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', + LpUniCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE', + LpUniLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974', + LpUniMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225', + LpUniRENWETH: '0x8Bd1661Da98EBDd3BD080F0bE4e6d9bE8cE9858c', + LpUniSNXWETH: '0x43AE24960e5534731Fc831386c07755A2dc33D47', + LpUniUNIWETH: '0xd3d2E2692501A5c9Ca623199D38826e513033a17', + LpUniUSDCWETH: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc', + LpUniWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416', + LpUniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', + LpBalWBTCWETH: '0x1efF8aF5D577060BA4ac8A29A13525bb0Ee2A3D5', }, }, }; diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index bd284dee..466a5abf 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -170,20 +170,21 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { LpUSDT: mockTokens.LpUSDT.address, LpWBTC: mockTokens.LpWBTC.address, LpWETH: mockTokens.LpWETH.address, - LpDAIWETH: mockTokens.LpDAIWETH.address, - LpWBTCWETH: mockTokens.LpWBTCWETH.address, - LpAAVEWETH: mockTokens.LpAAVEWETH.address, - LpBATWETH: mockTokens.LpBATWETH.address, - LpUSDCDAI: mockTokens.LpUSDCDAI.address, - LpCRVWETH: mockTokens.LpCRVWETH.address, - LpLINKWETH: mockTokens.LpLINKWETH.address, - LpMKRWETH: mockTokens.LpMKRWETH.address, - LpRENWETH: mockTokens.LpRENWETH.address, - LpSNXWETH: mockTokens.LpSNXWETH.address, - LpUNIWETH: mockTokens.LpUNIWETH.address, - LpUSDCWETH: mockTokens.LpUSDCWETH.address, - LpWBTCUSDC: mockTokens.LpWBTCUSDC.address, - LpYFIWETH: mockTokens.LpYFIWETH.address, + LpUniDAIWETH: mockTokens.LpUniDAIWETH.address, + LpUniWBTCWETH: mockTokens.LpUniWBTCWETH.address, + LpUniAAVEWETH: mockTokens.LpUniAAVEWETH.address, + LpUniBATWETH: mockTokens.LpUniBATWETH.address, + LpUniUSDCDAI: mockTokens.LpUniUSDCDAI.address, + LpUniCRVWETH: mockTokens.LpUniCRVWETH.address, + LpUniLINKWETH: mockTokens.LpUniLINKWETH.address, + LpUniMKRWETH: mockTokens.LpUniMKRWETH.address, + LpUniRENWETH: mockTokens.LpUniRENWETH.address, + LpUniSNXWETH: mockTokens.LpUniSNXWETH.address, + LpUniUNIWETH: mockTokens.LpUniUNIWETH.address, + LpUniUSDCWETH: mockTokens.LpUniUSDCWETH.address, + LpUniWBTCUSDC: mockTokens.LpUniWBTCUSDC.address, + LpUniYFIWETH: mockTokens.LpUniYFIWETH.address, + LpBalWBTCWETH: mockTokens.LpBalWBTCWETH.address, USD: USD_ADDRESS, }, fallbackOracle diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-lp/__setup.spec.ts index 72c5e01b..d38df0f9 100644 --- a/test-suites/test-lp/__setup.spec.ts +++ b/test-suites/test-lp/__setup.spec.ts @@ -170,20 +170,21 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { LpUSDT: mockTokens.LpUSDT.address, LpWBTC: mockTokens.LpWBTC.address, LpWETH: mockTokens.LpWETH.address, - LpDAIWETH: mockTokens.LpDAIWETH.address, - LpWBTCWETH: mockTokens.LpWBTCWETH.address, - LpAAVEWETH: mockTokens.LpAAVEWETH.address, - LpBATWETH: mockTokens.LpBATWETH.address, - LpUSDCDAI: mockTokens.LpUSDCDAI.address, - LpCRVWETH: mockTokens.LpCRVWETH.address, - LpLINKWETH: mockTokens.LpLINKWETH.address, - LpMKRWETH: mockTokens.LpMKRWETH.address, - LpRENWETH: mockTokens.LpRENWETH.address, - LpSNXWETH: mockTokens.LpSNXWETH.address, - LpUNIWETH: mockTokens.LpUNIWETH.address, - LpUSDCWETH: mockTokens.LpUSDCWETH.address, - LpWBTCUSDC: mockTokens.LpWBTCUSDC.address, - LpYFIWETH: mockTokens.LpYFIWETH.address, + LpUniDAIWETH: mockTokens.LpUniDAIWETH.address, + LpUniWBTCWETH: mockTokens.LpUniWBTCWETH.address, + LpUniAAVEWETH: mockTokens.LpUniAAVEWETH.address, + LpUniBATWETH: mockTokens.LpUniBATWETH.address, + LpUniUSDCDAI: mockTokens.LpUniUSDCDAI.address, + LpUniCRVWETH: mockTokens.LpUniCRVWETH.address, + LpUniLINKWETH: mockTokens.LpUniLINKWETH.address, + LpUniMKRWETH: mockTokens.LpUniMKRWETH.address, + LpUniRENWETH: mockTokens.LpUniRENWETH.address, + LpUniSNXWETH: mockTokens.LpUniSNXWETH.address, + LpUniUNIWETH: mockTokens.LpUniUNIWETH.address, + LpUniUSDCWETH: mockTokens.LpUniUSDCWETH.address, + LpUniWBTCUSDC: mockTokens.LpUniWBTCUSDC.address, + LpUniYFIWETH: mockTokens.LpUniYFIWETH.address, + LpBalWBTCWETH: mockTokens.LpBalWBTCWETH.address, USD: USD_ADDRESS, }, fallbackOracle diff --git a/test-suites/test-lp/helpers/make-suite.ts b/test-suites/test-lp/helpers/make-suite.ts index 10499ecc..07d9a54c 100644 --- a/test-suites/test-lp/helpers/make-suite.ts +++ b/test-suites/test-lp/helpers/make-suite.ts @@ -136,7 +136,7 @@ export async function initializeMakeSuite() { const daiAddress = reservesTokens.find((token) => token.symbol === 'LpDAI')?.tokenAddress; const usdcAddress = reservesTokens.find((token) => token.symbol === 'LpUSDC')?.tokenAddress; - const aaveAddress = reservesTokens.find((token) => token.symbol === 'LpAAVEWETH')?.tokenAddress; + const aaveAddress = reservesTokens.find((token) => token.symbol === 'LpUniAAVEWETH')?.tokenAddress; const wethAddress = reservesTokens.find((token) => token.symbol === 'WETH')?.tokenAddress; if (!aDaiAddress || !aWEthAddress) { diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json b/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json index 1ffc911b..39461dfc 100644 --- a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json +++ b/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json @@ -243,7 +243,7 @@ ] }, { - "description": "User 0 deposits 1 WETH, user 1 deposits 100 LPLINKWETH as collateral and borrows 0.5 WETH at variable rate", + "description": "User 0 deposits 1 WETH, user 1 deposits 100 LPUNILINKWETH as collateral and borrows 0.5 WETH at variable rate", "actions": [ { "name": "mint", @@ -274,7 +274,7 @@ { "name": "mint", "args": { - "reserve": "LPLINKWETH", + "reserve": "LPUNILINKWETH", "amount": "100", "user": "1" }, @@ -283,7 +283,7 @@ { "name": "approve", "args": { - "reserve": "LPLINKWETH", + "reserve": "LPUNILINKWETH", "user": "1" }, "expected": "success" @@ -292,7 +292,7 @@ { "name": "deposit", "args": { - "reserve": "LPLINKWETH", + "reserve": "LPUNILINKWETH", "amount": "100", "user": "1" }, @@ -431,7 +431,7 @@ { "name": "withdraw", "args": { - "reserve": "LPLINKWETH", + "reserve": "LPUNILINKWETH", "amount": "-1", "user": "1" }, diff --git a/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json b/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json index b0cee5ee..49785753 100644 --- a/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json +++ b/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json @@ -133,12 +133,12 @@ ] }, { - "description": "User 1 Deposits 10 LPLINKWETH, disables WETH as collateral. Should revert as 10 LPLINKWETH are not enough to cover the debt (revert expected)", + "description": "User 1 Deposits 10 LPUNILINKWETH, disables WETH as collateral. Should revert as 10 LPUNILINKWETH are not enough to cover the debt (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "LPLINKWETH", + "reserve": "LPUNILINKWETH", "amount": "10", "user": "1" }, @@ -147,7 +147,7 @@ { "name": "approve", "args": { - "reserve": "LPLINKWETH", + "reserve": "LPUNILINKWETH", "user": "1" }, "expected": "success" @@ -155,7 +155,7 @@ { "name": "deposit", "args": { - "reserve": "LPLINKWETH", + "reserve": "LPUNILINKWETH", "amount": "10", "user": "1" }, @@ -173,12 +173,12 @@ ] }, { - "description": "User 1 Deposits 640 more LPLINKWETH (enough to cover the LPDAI debt), disables WETH as collateral", + "description": "User 1 Deposits 640 more LPUNILINKWETH (enough to cover the LPDAI debt), disables WETH as collateral", "actions": [ { "name": "mint", "args": { - "reserve": "LPLINKWETH", + "reserve": "LPUNILINKWETH", "amount": "640", "user": "1" }, @@ -187,7 +187,7 @@ { "name": "deposit", "args": { - "reserve": "LPLINKWETH", + "reserve": "LPUNILINKWETH", "amount": "640", "user": "1" }, @@ -205,12 +205,12 @@ ] }, { - "description": "User 1 disables LPLINKWETH as collateral (revert expected)", + "description": "User 1 disables LPUNILINKWETH as collateral (revert expected)", "actions": [ { "name": "setUseAsCollateral", "args": { - "reserve": "LPLINKWETH", + "reserve": "LPUNILINKWETH", "user": "1", "useAsCollateral": "false" }, From 0302339892926674b0d6996eb02d9c31ea518cf0 Mon Sep 17 00:00:00 2001 From: eboado Date: Thu, 18 Feb 2021 13:29:17 +0100 Subject: [PATCH 104/219] - Changed modifier on batchInitReserve() --- contracts/protocol/lendingpool/LendingPoolConfigurator.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol index f42415ca..b9811311 100644 --- a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol @@ -60,7 +60,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur /** * @dev Initializes reserves in batch **/ - function batchInitReserve(InitReserveInput[] calldata inputParams) public onlyPoolAdmin { + function batchInitReserve(InitReserveInput[] calldata inputParams) external onlyPoolAdmin { ILendingPool cachedPool = pool; for (uint256 i = 0; i < inputParams.length; i++) { _initReserve(cachedPool, inputParams[i]); From 5ca1a4f05b23c297c3e8241e3c6960f8d184de96 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 18 Feb 2021 16:49:29 -0500 Subject: [PATCH 105/219] Re-enabled Sec 3 --- tasks/full/1_address_provider.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tasks/full/1_address_provider.ts b/tasks/full/1_address_provider.ts index ae5fabc0..87e3e23d 100644 --- a/tasks/full/1_address_provider.ts +++ b/tasks/full/1_address_provider.ts @@ -82,15 +82,14 @@ task( // 2. Deploy address provider and set genesis manager const addressesProvider = await deployLendingPoolAddressesProvider(MarketId, verify); - // TEMPORARILY DISABLING SEC. 3 FOR GOVERNANCE USE - + // DISABLE SEC. 3 FOR GOVERNANCE USE! // 3. Set the provider at the Registry - // await waitForTx( - // await addressesProviderRegistry.registerAddressesProvider( - // addressesProvider.address, - // ProviderId - // ) - // ); + await waitForTx( + await addressesProviderRegistry.registerAddressesProvider( + addressesProvider.address, + ProviderId + ) + ); // 4. Set pool admins From a0dbf13d6041deb8866e8eb6b85cfdc48d8a8423 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 18 Feb 2021 16:49:54 -0500 Subject: [PATCH 106/219] Reused same Registry owner & price oracle --- markets/lp/commons.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index da376b39..8ee7e247 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -168,8 +168,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', }, - ProviderRegistryOwner: { // TEMPORARILY USING MY DEPLOYER - [eEthereumNetwork.kovan]: '0x18d9bA2baEfBdE0FF137C4ad031427EF205f1Fd9',//'0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', + ProviderRegistryOwner: { // DEPLOYED WITH CORRECT ADDRESS + [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', [eEthereumNetwork.coverage]: '', @@ -181,7 +181,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '', //'0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', // Need to re-deploy because of onlyOwner + [eEthereumNetwork.kovan]: '',//'0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', // Need to re-deploy because of onlyOwner [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', [eEthereumNetwork.main]: '', //'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', // Need to re-deploy because of onlyOwner [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', @@ -208,7 +208,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [EthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', // Need to re-deploy because of onlyOwner + [EthereumNetwork.kovan]: '0x8fb777d67e9945e2c01936e319057f9d41d559e6', // Need to re-deploy because of onlyOwner [EthereumNetwork.ropsten]: ZERO_ADDRESS, [EthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', // Need to re-deploy because of onlyOwner [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', From f44879e625b666983cd91233b601c7cc7b1debbc Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Thu, 18 Feb 2021 16:50:15 -0500 Subject: [PATCH 107/219] Fixed missing "waitForTx" --- tasks/full/3_oracles.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index 677681ec..67a8fbd7 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -48,23 +48,17 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') }; const [tokens, aggregators] = getPairsTokenAggregator(tokensToWatch, chainlinkAggregators); - // const aaveOracle = notFalsyOrZeroAddress(aaveOracleAddress) - // ? await getAaveOracle(aaveOracleAddress) - // : await deployAaveOracle( - // [tokens, aggregators, fallbackOracleAddress, await getWethAddress(poolConfig)], - // verify - // ); - let aaveOracle: AaveOracle; if (notFalsyOrZeroAddress(aaveOracleAddress)) { aaveOracle = await getAaveOracle(aaveOracleAddress); - await aaveOracle.setAssetSources(tokens, aggregators); + await waitForTx(await aaveOracle.setAssetSources(tokens, aggregators)); } else { aaveOracle = await deployAaveOracle( [tokens, aggregators, fallbackOracleAddress, await getWethAddress(poolConfig)], verify ); } + const lendingRateOracle = notFalsyOrZeroAddress(lendingRateOracleAddress) ? await getLendingRateOracle(lendingRateOracleAddress) : await deployLendingRateOracle(verify); From ecbe881bcc61835f863761bec49ea7884ffe861a Mon Sep 17 00:00:00 2001 From: The3D Date: Fri, 19 Feb 2021 17:02:34 +0100 Subject: [PATCH 108/219] Added initial configuration --- markets/arbitrum/commons.ts | 0 markets/arbitrum/index.ts | 1 + markets/arbitrum/rateStrategies.ts | 0 markets/arbitrum/reservesConfigs.ts | 0 markets/bsc/commons.ts | 0 markets/bsc/index.ts | 1 + markets/bsc/rateStrategies.ts | 0 markets/bsc/reservesConfigs.ts | 0 markets/matic/commons.ts | 0 markets/matic/index.ts | 1 + markets/matic/rateStrategies.ts | 0 markets/matic/reservesConfigs.ts | 0 markets/ovm/commons.ts | 0 markets/ovm/index.ts | 1 + markets/ovm/rateStrategies.ts | 0 markets/ovm/reservesConfigs.ts | 0 markets/solana/commons.ts | 0 markets/solana/index.ts | 1 + markets/solana/rateStrategies.ts | 0 markets/solana/reservesConfigs.ts | 0 markets/xdai/commons.ts | 0 markets/xdai/index.ts | 1 + markets/xdai/rateStrategies.ts | 0 markets/xdai/reservesConfigs.ts | 0 markets/zksync/commons.ts | 0 markets/zksync/index.ts | 1 + markets/zksync/rateStrategies.ts | 0 markets/zksync/reservesConfigs.ts | 0 28 files changed, 7 insertions(+) create mode 100644 markets/arbitrum/commons.ts create mode 100644 markets/arbitrum/index.ts create mode 100644 markets/arbitrum/rateStrategies.ts create mode 100644 markets/arbitrum/reservesConfigs.ts create mode 100644 markets/bsc/commons.ts create mode 100644 markets/bsc/index.ts create mode 100644 markets/bsc/rateStrategies.ts create mode 100644 markets/bsc/reservesConfigs.ts create mode 100644 markets/matic/commons.ts create mode 100644 markets/matic/index.ts create mode 100644 markets/matic/rateStrategies.ts create mode 100644 markets/matic/reservesConfigs.ts create mode 100644 markets/ovm/commons.ts create mode 100644 markets/ovm/index.ts create mode 100644 markets/ovm/rateStrategies.ts create mode 100644 markets/ovm/reservesConfigs.ts create mode 100644 markets/solana/commons.ts create mode 100644 markets/solana/index.ts create mode 100644 markets/solana/rateStrategies.ts create mode 100644 markets/solana/reservesConfigs.ts create mode 100644 markets/xdai/commons.ts create mode 100644 markets/xdai/index.ts create mode 100644 markets/xdai/rateStrategies.ts create mode 100644 markets/xdai/reservesConfigs.ts create mode 100644 markets/zksync/commons.ts create mode 100644 markets/zksync/index.ts create mode 100644 markets/zksync/rateStrategies.ts create mode 100644 markets/zksync/reservesConfigs.ts diff --git a/markets/arbitrum/commons.ts b/markets/arbitrum/commons.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/arbitrum/index.ts b/markets/arbitrum/index.ts new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/markets/arbitrum/index.ts @@ -0,0 +1 @@ + diff --git a/markets/arbitrum/rateStrategies.ts b/markets/arbitrum/rateStrategies.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/arbitrum/reservesConfigs.ts b/markets/arbitrum/reservesConfigs.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/bsc/commons.ts b/markets/bsc/commons.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/bsc/index.ts b/markets/bsc/index.ts new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/markets/bsc/index.ts @@ -0,0 +1 @@ + diff --git a/markets/bsc/rateStrategies.ts b/markets/bsc/rateStrategies.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/bsc/reservesConfigs.ts b/markets/bsc/reservesConfigs.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/matic/index.ts b/markets/matic/index.ts new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/markets/matic/index.ts @@ -0,0 +1 @@ + diff --git a/markets/matic/rateStrategies.ts b/markets/matic/rateStrategies.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/matic/reservesConfigs.ts b/markets/matic/reservesConfigs.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/ovm/commons.ts b/markets/ovm/commons.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/ovm/index.ts b/markets/ovm/index.ts new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/markets/ovm/index.ts @@ -0,0 +1 @@ + diff --git a/markets/ovm/rateStrategies.ts b/markets/ovm/rateStrategies.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/ovm/reservesConfigs.ts b/markets/ovm/reservesConfigs.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/solana/commons.ts b/markets/solana/commons.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/solana/index.ts b/markets/solana/index.ts new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/markets/solana/index.ts @@ -0,0 +1 @@ + diff --git a/markets/solana/rateStrategies.ts b/markets/solana/rateStrategies.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/solana/reservesConfigs.ts b/markets/solana/reservesConfigs.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/xdai/commons.ts b/markets/xdai/commons.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/xdai/index.ts b/markets/xdai/index.ts new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/markets/xdai/index.ts @@ -0,0 +1 @@ + diff --git a/markets/xdai/rateStrategies.ts b/markets/xdai/rateStrategies.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/xdai/reservesConfigs.ts b/markets/xdai/reservesConfigs.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/zksync/commons.ts b/markets/zksync/commons.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/zksync/index.ts b/markets/zksync/index.ts new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/markets/zksync/index.ts @@ -0,0 +1 @@ + diff --git a/markets/zksync/rateStrategies.ts b/markets/zksync/rateStrategies.ts new file mode 100644 index 00000000..e69de29b diff --git a/markets/zksync/reservesConfigs.ts b/markets/zksync/reservesConfigs.ts new file mode 100644 index 00000000..e69de29b From 5965ef09d4ee68e66203d33b378ddbf521964986 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 15:50:06 -0500 Subject: [PATCH 109/219] Fixed names & added prefixes --- helpers/init-helpers.ts | 16 +-- helpers/types.ts | 124 ++++++++++++----------- markets/aave/commons.ts | 45 +++++---- markets/lp/commons.ts | 198 +++++++++++++++++++------------------ markets/lp/index.ts | 160 +++++++++++++++--------------- tasks/dev/5_initialize.ts | 11 ++- tasks/full/5_initialize.ts | 14 ++- 7 files changed, 302 insertions(+), 266 deletions(-) diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index e2ced0d7..3f6ce5f4 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -44,6 +44,10 @@ export const chooseATokenDeployment = (id: eContractid) => { export const initReservesByHelper = async ( reservesParams: iMultiPoolsAssets, tokenAddresses: { [symbol: string]: tEthereumAddress }, + aTokenNamePrefix: string, + stableDebtTokenNamePrefix: string, + variableDebtTokenNamePrefix: string, + symbolPrefix: string, admin: tEthereumAddress, treasuryAddress: tEthereumAddress, incentivesController: tEthereumAddress, @@ -194,12 +198,12 @@ export const initReservesByHelper = async ( treasury: treasuryAddress, incentivesController: ZERO_ADDRESS, underlyingAssetName: reserveSymbols[i], - aTokenName: `Aave interest bearing ${reserveSymbols[i]}`, - aTokenSymbol: `a${reserveSymbols[i]}`, - variableDebtTokenName: `Aave variable debt bearing ${reserveSymbols[i]}`, - variableDebtTokenSymbol: `variableDebt${reserveSymbols[i]}`, - stableDebtTokenName: `Aave stable debt bearing ${reserveSymbols[i]}`, - stableDebtTokenSymbol: `stableDebt${reserveSymbols[i]}` + aTokenName: `${aTokenNamePrefix} ${reserveSymbols[i]}`, + aTokenSymbol: `a${symbolPrefix}${reserveSymbols[i]}`, + variableDebtTokenName: `${variableDebtTokenNamePrefix} ${symbolPrefix}${reserveSymbols[i]}`, + variableDebtTokenSymbol: `variableDebt${symbolPrefix}${reserveSymbols[i]}`, + stableDebtTokenName: `${stableDebtTokenNamePrefix} ${reserveSymbols[i]}`, + stableDebtTokenSymbol: `stableDebt${symbolPrefix}${reserveSymbols[i]}` }); } diff --git a/helpers/types.ts b/helpers/types.ts index 54c75180..57a9bfd3 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -205,26 +205,26 @@ export interface iAssetBase { USD: T; REN: T; ENJ: T; - LpWETH: T; - LpWBTC: T; - LpDAI: T; - LpUSDC: T; - LpUSDT: T; - LpUniDAIWETH: T; - LpUniWBTCWETH: T; - LpUniAAVEWETH: T; - LpUniBATWETH: T; - LpUniUSDCDAI: T; - LpUniCRVWETH: T; - LpUniLINKWETH: T; - LpUniMKRWETH: T; - LpUniRENWETH: T; - LpUniSNXWETH: T; - LpUniUNIWETH: T; - LpUniUSDCWETH: T; - LpUniWBTCUSDC: T; - LpUniYFIWETH: T; - LpBalWBTCWETH: T; + // LpWETH: T; + // LpWBTC: T; + // LpDAI: T; + // LpUSDC: T; + // LpUSDT: T; + UniDAIWETH: T; + UniWBTCWETH: T; + UniAAVEWETH: T; + UniBATWETH: T; + UniUSDCDAI: T; + UniCRVWETH: T; + UniLINKWETH: T; + UniMKRWETH: T; + UniRENWETH: T; + UniSNXWETH: T; + UniUNIWETH: T; + UniUSDCWETH: T; + UniWBTCUSDC: T; + UniYFIWETH: T; + BptWBTCWETH: T; } export type iAssetsWithoutETH = Omit, 'ETH'>; @@ -257,26 +257,26 @@ export type iAavePoolAssets = Pick< export type iLpPoolAssets = Pick< iAssetsWithoutUSD, - | 'LpDAI' - | 'LpUSDC' - | 'LpUSDT' - | 'LpWBTC' - | 'LpWETH' - | 'LpUniDAIWETH' - | 'LpUniWBTCWETH' - | 'LpUniAAVEWETH' - | 'LpUniBATWETH' - | 'LpUniUSDCDAI' - | 'LpUniCRVWETH' - | 'LpUniLINKWETH' - | 'LpUniMKRWETH' - | 'LpUniRENWETH' - | 'LpUniSNXWETH' - | 'LpUniUNIWETH' - | 'LpUniUSDCWETH' - | 'LpUniWBTCUSDC' - | 'LpUniYFIWETH' - | 'LpBalWBTCWETH' + | 'DAI' + | 'USDC' + | 'USDT' + | 'WBTC' + | 'WETH' + | 'UniDAIWETH' + | 'UniWBTCWETH' + | 'UniAAVEWETH' + | 'UniBATWETH' + | 'UniUSDCDAI' + | 'UniCRVWETH' + | 'UniLINKWETH' + | 'UniMKRWETH' + | 'UniRENWETH' + | 'UniSNXWETH' + | 'UniUNIWETH' + | 'UniUSDCWETH' + | 'UniWBTCUSDC' + | 'UniYFIWETH' + | 'BptWBTCWETH' >; export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; @@ -307,26 +307,26 @@ export enum TokenContractId { YFI = 'YFI', UNI = 'UNI', ENJ = 'ENJ', - LpWETH = 'LpWETH', - LpWBTC = 'LpWBTC', - LpDAI = 'LpDAI', - LpUSDC = 'LpUSDC', - LpUSDT = 'LpUSDT', - LpUniDAIWETH = 'LpUniDAIWETH', - LpUniWBTCWETH = 'LpUniWBTCWETH', - LpUniAAVEWETH = 'LpUniAAVEWETH', - LpUniBATWETH = 'LpUniBATWETH', - LpUniUSDCDAI = 'LpUniUSDCDAI', - LpUniCRVWETH = 'LpUniCRVWETH', - LpUniLINKWETH = 'LpUniLINKWETH', - LpUniMKRWETH = 'LpUniMKRWETH', - LpUniRENWETH = 'LpUniRENWETH', - LpUniSNXWETH = 'LpUniSNXWETH', - LpUniUNIWETH = 'LpUniUNIWETH', - LpUniUSDCWETH = 'LpUniUSDCWETH', - LpUniWBTCUSDC = 'LpUniWBTCUSDC', - LpUniYFIWETH = 'LpUniYFIWETH', - LpBalWBTCWETH = 'LpBalWBTCWETH', + // LpWETH = 'LpWETH', + // LpWBTC = 'LpWBTC', + // LpDAI = 'LpDAI', + // LpUSDC = 'LpUSDC', + // LpUSDT = 'LpUSDT', + UniDAIWETH = 'UniDAIWETH', + UniWBTCWETH = 'UniWBTCWETH', + UniAAVEWETH = 'UniAAVEWETH', + UniBATWETH = 'UniBATWETH', + UniUSDCDAI = 'UniUSDCDAI', + UniCRVWETH = 'UniCRVWETH', + UniLINKWETH = 'UniLINKWETH', + UniMKRWETH = 'UniMKRWETH', + UniRENWETH = 'UniRENWETH', + UniSNXWETH = 'UniSNXWETH', + UniUNIWETH = 'UniUNIWETH', + UniUSDCWETH = 'UniUSDCWETH', + UniWBTCUSDC = 'UniWBTCUSDC', + UniYFIWETH = 'UniYFIWETH', + BptWBTCWETH = 'BptWBTCWETH', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { @@ -428,6 +428,10 @@ export interface ILendingRate { export interface ICommonConfiguration { MarketId: string; + ATokenNamePrefix: string; + StableDebtTokenNamePrefix: string; + VariableDebtTokenNamePrefix: string; + SymbolPrefix: string; ProviderId: number; ProtocolGlobalParams: IProtocolGlobalConfig; Mocks: IMocksConfig; diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index f5992dba..5571be27 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -23,35 +23,38 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), - LpDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - LpUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), - LpWETH: oneEther.toFixed(), - LpUniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), - LpUniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), - LpUniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), - LpUniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), - LpUniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpBalWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + // LpDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + // LpUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + // LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + // LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), + // LpWETH: oneEther.toFixed(), + UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), + UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), + UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), + UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), + UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), + BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; - // ---------------- // PROTOCOL GLOBAL PARAMS // ---------------- export const CommonsConfig: ICommonConfiguration = { MarketId: 'Commons', + ATokenNamePrefix: 'Aave interest bearing', + StableDebtTokenNamePrefix: 'Aave stable debt bearing', + VariableDebtTokenNamePrefix: 'Aave variable debt bearing', + SymbolPrefix: '', ProviderId: 0, ProtocolGlobalParams: { TokenDistributorPercentageBase: '10000', diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index 8ee7e247..d29b7d29 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -23,26 +23,26 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), - LpDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - LpUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), - LpWETH: oneEther.toFixed(), - LpUniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), - LpUniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), - LpUniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), - LpUniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), - LpUniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpBalWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + // DAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + // USDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + // USDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + // WBTC: oneEther.multipliedBy('47.332685').toFixed(), + // WETH: oneEther.toFixed(), + UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), + UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), + UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), + UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), + UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), + BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; // ---------------- @@ -51,6 +51,10 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { export const CommonsConfig: ICommonConfiguration = { MarketId: 'Commons', + ATokenNamePrefix: 'Aave AMM Market', + StableDebtTokenNamePrefix: 'Aave AMM Market stable debt', + VariableDebtTokenNamePrefix: 'Aave AMM Market variable debt', + SymbolPrefix: 'Amm', ProviderId: 0, ProtocolGlobalParams: { TokenDistributorPercentageBase: '10000', @@ -72,64 +76,64 @@ export const CommonsConfig: ICommonConfiguration = { }, // TODO: reorg alphabetically, checking the reason of tests failing LendingRateOracleRatesCommon: { - LpWETH: { + WETH: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - LpDAI: { + DAI: { borrowRate: oneRay.multipliedBy(0.039).toFixed(), }, - LpUSDC: { + USDC: { borrowRate: oneRay.multipliedBy(0.039).toFixed(), }, - LpUSDT: { + USDT: { borrowRate: oneRay.multipliedBy(0.035).toFixed(), }, - LpWBTC: { + WBTC: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - LpUniDAIWETH: { + UniDAIWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniWBTCWETH: { + UniWBTCWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniAAVEWETH:{ + UniAAVEWETH:{ borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniBATWETH: { + UniBATWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniUSDCDAI: { + UniUSDCDAI: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniCRVWETH: { + UniCRVWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniLINKWETH: { + UniLINKWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniMKRWETH: { + UniMKRWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniRENWETH: { + UniRENWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniSNXWETH: { + UniSNXWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniUNIWETH: { + UniUNIWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniUSDCWETH: { + UniUSDCWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniWBTCUSDC: { + UniWBTCUSDC: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpUniYFIWETH: { + UniYFIWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - LpBalWBTCWETH: { + BptWBTCWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, }, @@ -227,71 +231,71 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.buidlerevm]: {}, [EthereumNetwork.kovan]: { - LpUSDT: '0x0bF499444525a23E7Bb61997539725cA2e928138', - LpWBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', - LpUSDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', - LpDAI:'0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', - LpUniDAIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', // Mock oracles - LpUniWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUniAAVEWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUniBATWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUniUSDCDAI: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUniCRVWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUniLINKWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUniMKRWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUniRENWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUniSNXWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUniUNIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUniUSDCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUniWBTCUSDC: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpUniYFIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - LpBalWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + USDT: '0x0bF499444525a23E7Bb61997539725cA2e928138', + WBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', + USDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', + DAI:'0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', + UniDAIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', // Mock oracles + UniWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniAAVEWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniBATWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniUSDCDAI: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniCRVWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniLINKWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniMKRWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniRENWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniSNXWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniUNIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniUSDCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniWBTCUSDC: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniYFIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + BptWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [EthereumNetwork.ropsten]: { }, [EthereumNetwork.main]: { - LpUSDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', - LpWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', - LpUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', - LpDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', - LpUniDAIWETH: '0xf4071801C4421Db7e63DaC15B9432e50C44a7F42', - LpUniWBTCWETH: ZERO_ADDRESS, - LpUniAAVEWETH: ZERO_ADDRESS, - LpUniBATWETH: ZERO_ADDRESS, - LpUniUSDCDAI: ZERO_ADDRESS, - LpUniCRVWETH: ZERO_ADDRESS, - LpUniLINKWETH: ZERO_ADDRESS, - LpUniMKRWETH: ZERO_ADDRESS, - LpUniRENWETH: ZERO_ADDRESS, - LpUniSNXWETH: ZERO_ADDRESS, - LpUniUNIWETH: ZERO_ADDRESS, - LpUniUSDCWETH: ZERO_ADDRESS, - LpUniWBTCUSDC: ZERO_ADDRESS, - LpUniYFIWETH: ZERO_ADDRESS, - LpBalWBTCWETH: ZERO_ADDRESS, + USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', + WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', + USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', + DAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', + UniDAIWETH: '0xf4071801C4421Db7e63DaC15B9432e50C44a7F42', + UniWBTCWETH: ZERO_ADDRESS, + UniAAVEWETH: ZERO_ADDRESS, + UniBATWETH: ZERO_ADDRESS, + UniUSDCDAI: ZERO_ADDRESS, + UniCRVWETH: ZERO_ADDRESS, + UniLINKWETH: ZERO_ADDRESS, + UniMKRWETH: ZERO_ADDRESS, + UniRENWETH: ZERO_ADDRESS, + UniSNXWETH: ZERO_ADDRESS, + UniUNIWETH: ZERO_ADDRESS, + UniUSDCWETH: ZERO_ADDRESS, + UniWBTCUSDC: ZERO_ADDRESS, + UniYFIWETH: ZERO_ADDRESS, + BptWBTCWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [EthereumNetwork.tenderlyMain]: { - LpUSDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', - LpWBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', - LpUSDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', - LpDAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', - LpUniDAIWETH: ZERO_ADDRESS, - LpUniWBTCWETH: ZERO_ADDRESS, - LpUniAAVEWETH: ZERO_ADDRESS, - LpUniBATWETH: ZERO_ADDRESS, - LpUniUSDCDAI: ZERO_ADDRESS, - LpUniCRVWETH: ZERO_ADDRESS, - LpUniLINKWETH: ZERO_ADDRESS, - LpUniMKRWETH: ZERO_ADDRESS, - LpUniRENWETH: ZERO_ADDRESS, - LpUniSNXWETH: ZERO_ADDRESS, - LpUniUNIWETH: ZERO_ADDRESS, - LpUniUSDCWETH: ZERO_ADDRESS, - LpUniWBTCUSDC: ZERO_ADDRESS, - LpUniYFIWETH: ZERO_ADDRESS, - LpBalWBTCWETH: ZERO_ADDRESS, + USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', + WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', + USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', + DAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', + UniDAIWETH: ZERO_ADDRESS, + UniWBTCWETH: ZERO_ADDRESS, + UniAAVEWETH: ZERO_ADDRESS, + UniBATWETH: ZERO_ADDRESS, + UniUSDCDAI: ZERO_ADDRESS, + UniCRVWETH: ZERO_ADDRESS, + UniLINKWETH: ZERO_ADDRESS, + UniMKRWETH: ZERO_ADDRESS, + UniRENWETH: ZERO_ADDRESS, + UniSNXWETH: ZERO_ADDRESS, + UniUNIWETH: ZERO_ADDRESS, + UniUSDCWETH: ZERO_ADDRESS, + UniWBTCUSDC: ZERO_ADDRESS, + UniYFIWETH: ZERO_ADDRESS, + BptWBTCWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, }, diff --git a/markets/lp/index.ts b/markets/lp/index.ts index c1105a05..5886bf85 100644 --- a/markets/lp/index.ts +++ b/markets/lp/index.ts @@ -33,98 +33,98 @@ export const lpConfig: ILpConfiguration = { MarketId: 'Aave LP market', ProviderId: 2, ReservesConfig: { - LpWETH: strategyWETH, - LpDAI: strategyDAI, - LpUSDC: strategyUSDC, - LpUSDT: strategyUSDT, - LpWBTC: strategyWBTC, - LpUniDAIWETH: strategyDAIWETH, - LpUniWBTCWETH: strategyWBTCWETH, - LpUniAAVEWETH: strategyAAVEWETH, - LpUniBATWETH: strategyBATWETH, - LpUniUSDCDAI: strategyUSDCDAI, - LpUniCRVWETH: strategyCRVWETH, - LpUniLINKWETH: strategyLINKWETH, - LpUniMKRWETH: strategyMKRWETH, - LpUniRENWETH: strategyRENWETH, - LpUniSNXWETH: strategySNXWETH, - LpUniUNIWETH: strategyUNIWETH, - LpUniUSDCWETH: strategyUSDCWETH, - LpUniWBTCUSDC: strategyWBTCUSDC, - LpUniYFIWETH: strategyYFIWETH, - LpBalWBTCWETH: strategyWBTCWETH, + WETH: strategyWETH, + DAI: strategyDAI, + USDC: strategyUSDC, + USDT: strategyUSDT, + WBTC: strategyWBTC, + UniDAIWETH: strategyDAIWETH, + UniWBTCWETH: strategyWBTCWETH, + UniAAVEWETH: strategyAAVEWETH, + UniBATWETH: strategyBATWETH, + UniUSDCDAI: strategyUSDCDAI, + UniCRVWETH: strategyCRVWETH, + UniLINKWETH: strategyLINKWETH, + UniMKRWETH: strategyMKRWETH, + UniRENWETH: strategyRENWETH, + UniSNXWETH: strategySNXWETH, + UniUNIWETH: strategyUNIWETH, + UniUSDCWETH: strategyUSDCWETH, + UniWBTCUSDC: strategyWBTCUSDC, + UniYFIWETH: strategyYFIWETH, + BptWBTCWETH: strategyWBTCWETH, }, ReserveAssets: { [eEthereumNetwork.buidlerevm]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.coverage]: {}, [EthereumNetwork.kovan]: { - LpDAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', - LpUSDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', - LpUSDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', - LpWBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', - LpWETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', - LpUniDAIWETH: '0x7e48b02B21D784e79E17b06988fc150c8b5945df', - LpUniWBTCWETH: '0x4Fd18882730dc5f945d5049C3f99Ee43CCA1F3d9', - LpUniAAVEWETH: '0xC173038224d47e11962bb0Bd10e036c573C57dF0', - LpUniBATWETH: '0xfC482c56A91Cc92019FF6522B2FB76F41B7e2535', - LpUniUSDCDAI: '0xFD0795980D4c37Fd867228C86A1f7693C9219142', - LpUniCRVWETH: '0xC7f1899F8B5861d8A3Ce1385194bc130A15C8a74', - LpUniLINKWETH: '0xCe2355F9249ced9E51ecc35AbB749352C2557D0d', - LpUniMKRWETH: '0xDCf7A28f4102B7f5813148cCEFb02134648E6F0C', - LpUniRENWETH: '0xe46C9459833bBa061471DF2a383D27a20FE97E23', - LpUniSNXWETH: '0xAa5826dea7cfEc02AcB644b24387bE2648feAbB9', - LpUniUNIWETH: '0xD4C255B5500cFB262EB5F9105Ea546Aa0610A0d3', - LpUniUSDCWETH: '0x509f6ce2F9718E3dd854cCE1857FabCc59C6dd5e', - LpUniWBTCUSDC: '0x9D15e3A14926A16C9B285A5c6bd6c9e82d5F8031', - LpUniYFIWETH: '0xC6Dc783B3C2E2Cbf71791d253f8b4993D40DBf98', - LpBalWBTCWETH: '0x930087451C5940B28bE556d32a4CF22D5d9754A1', + DAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', + USDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', + USDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', + WBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', + WETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', + UniDAIWETH: '0x7e48b02B21D784e79E17b06988fc150c8b5945df', + UniWBTCWETH: '0x4Fd18882730dc5f945d5049C3f99Ee43CCA1F3d9', + UniAAVEWETH: '0xC173038224d47e11962bb0Bd10e036c573C57dF0', + UniBATWETH: '0xfC482c56A91Cc92019FF6522B2FB76F41B7e2535', + UniUSDCDAI: '0xFD0795980D4c37Fd867228C86A1f7693C9219142', + UniCRVWETH: '0xC7f1899F8B5861d8A3Ce1385194bc130A15C8a74', + UniLINKWETH: '0xCe2355F9249ced9E51ecc35AbB749352C2557D0d', + UniMKRWETH: '0xDCf7A28f4102B7f5813148cCEFb02134648E6F0C', + UniRENWETH: '0xe46C9459833bBa061471DF2a383D27a20FE97E23', + UniSNXWETH: '0xAa5826dea7cfEc02AcB644b24387bE2648feAbB9', + UniUNIWETH: '0xD4C255B5500cFB262EB5F9105Ea546Aa0610A0d3', + UniUSDCWETH: '0x509f6ce2F9718E3dd854cCE1857FabCc59C6dd5e', + UniWBTCUSDC: '0x9D15e3A14926A16C9B285A5c6bd6c9e82d5F8031', + UniYFIWETH: '0xC6Dc783B3C2E2Cbf71791d253f8b4993D40DBf98', + BptWBTCWETH: '0x930087451C5940B28bE556d32a4CF22D5d9754A1', }, [EthereumNetwork.ropsten]: { }, [EthereumNetwork.main]: { - LpDAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - LpUSDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - LpUSDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', - LpWBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', - LpWETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - LpUniDAIWETH: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', - LpUniWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', - LpUniAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f', - LpUniBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838', - LpUniUSDCDAI: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', - LpUniCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE', - LpUniLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974', - LpUniMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225', - LpUniRENWETH: '0x8Bd1661Da98EBDd3BD080F0bE4e6d9bE8cE9858c', - LpUniSNXWETH: '0x43AE24960e5534731Fc831386c07755A2dc33D47', - LpUniUNIWETH: '0xd3d2E2692501A5c9Ca623199D38826e513033a17', - LpUniUSDCWETH: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc', - LpUniWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416', - LpUniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', - LpBalWBTCWETH: '0x1efF8aF5D577060BA4ac8A29A13525bb0Ee2A3D5', + DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + UniDAIWETH: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', + UniWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', + UniAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f', + UniBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838', + UniUSDCDAI: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', + UniCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE', + UniLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974', + UniMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225', + UniRENWETH: '0x8Bd1661Da98EBDd3BD080F0bE4e6d9bE8cE9858c', + UniSNXWETH: '0x43AE24960e5534731Fc831386c07755A2dc33D47', + UniUNIWETH: '0xd3d2E2692501A5c9Ca623199D38826e513033a17', + UniUSDCWETH: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc', + UniWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416', + UniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', + BptWBTCWETH: '0x1efF8aF5D577060BA4ac8A29A13525bb0Ee2A3D5', }, [EthereumNetwork.tenderlyMain]: { - LpDAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - LpUSDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - LpUSDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', - LpWBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', - LpWETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - LpUniDAIWETH: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', - LpUniWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', - LpUniAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f', - LpUniBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838', - LpUniUSDCDAI: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', - LpUniCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE', - LpUniLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974', - LpUniMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225', - LpUniRENWETH: '0x8Bd1661Da98EBDd3BD080F0bE4e6d9bE8cE9858c', - LpUniSNXWETH: '0x43AE24960e5534731Fc831386c07755A2dc33D47', - LpUniUNIWETH: '0xd3d2E2692501A5c9Ca623199D38826e513033a17', - LpUniUSDCWETH: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc', - LpUniWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416', - LpUniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', - LpBalWBTCWETH: '0x1efF8aF5D577060BA4ac8A29A13525bb0Ee2A3D5', + DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + UniDAIWETH: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', + UniWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', + UniAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f', + UniBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838', + UniUSDCDAI: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', + UniCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE', + UniLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974', + UniMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225', + UniRENWETH: '0x8Bd1661Da98EBDd3BD080F0bE4e6d9bE8cE9858c', + UniSNXWETH: '0x43AE24960e5534731Fc831386c07755A2dc33D47', + UniUNIWETH: '0xd3d2E2692501A5c9Ca623199D38826e513033a17', + UniUSDCWETH: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc', + UniWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416', + UniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', + BptWBTCWETH: '0x1efF8aF5D577060BA4ac8A29A13525bb0Ee2A3D5', }, }, }; diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index 37744343..983b7454 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -31,7 +31,12 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') .setAction(async ({ verify, pool }, localBRE) => { await localBRE.run('set-DRE'); const poolConfig = loadPoolConfig(pool); - + const { + ATokenNamePrefix, + StableDebtTokenNamePrefix, + VariableDebtTokenNamePrefix, + SymbolPrefix, + } = poolConfig; const mockTokens = await getAllMockedTokens(); const allTokenAddresses = getAllTokenAddresses(mockTokens); @@ -52,6 +57,10 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') await initReservesByHelper( reservesParams, protoPoolReservesAddresses, + ATokenNamePrefix, + StableDebtTokenNamePrefix, + VariableDebtTokenNamePrefix, + SymbolPrefix, admin, treasuryAddress, ZERO_ADDRESS, diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index a8e93f7e..99725034 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -29,7 +29,15 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') await localBRE.run('set-DRE'); const network = localBRE.network.name; const poolConfig = loadPoolConfig(pool); - const { ReserveAssets, ReservesConfig, LendingPoolCollateralManager } = poolConfig as ICommonConfiguration; + const { + ATokenNamePrefix, + StableDebtTokenNamePrefix, + VariableDebtTokenNamePrefix, + SymbolPrefix, + ReserveAssets, + ReservesConfig, + LendingPoolCollateralManager + } = poolConfig as ICommonConfiguration; const reserveAssets = await getParamPerNetwork(ReserveAssets, network); @@ -47,6 +55,10 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') await initReservesByHelper( ReservesConfig, reserveAssets, + ATokenNamePrefix, + StableDebtTokenNamePrefix, + VariableDebtTokenNamePrefix, + SymbolPrefix, admin, treasuryAddress, ZERO_ADDRESS, From ebc147866f7b87eb6ea11ce61cbda04024083671 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 15:50:13 -0500 Subject: [PATCH 110/219] Fixed tests with new prefixes --- test-suites/test-aave/__setup.spec.ts | 55 ++++--- test-suites/test-lp/__setup.spec.ts | 56 ++++--- test-suites/test-lp/atoken-transfer.spec.ts | 2 +- test-suites/test-lp/helpers/make-suite.ts | 10 +- .../helpers/scenarios/borrow-negatives.json | 20 +-- .../scenarios/borrow-repay-stable.json | 142 ++++++++--------- .../scenarios/borrow-repay-variable.json | 144 +++++++++--------- .../helpers/scenarios/credit-delegation.json | 8 +- .../test-lp/helpers/scenarios/deposit.json | 42 ++--- .../scenarios/rebalance-stable-rate.json | 32 ++-- .../scenarios/set-use-as-collateral.json | 36 ++--- .../helpers/scenarios/swap-rate-mode.json | 44 +++--- .../helpers/scenarios/withdraw-negatives.json | 22 +-- .../test-lp/helpers/scenarios/withdraw.json | 76 ++++----- .../test-lp/helpers/utils/calculations.ts | 6 +- test-suites/test-lp/stable-token.spec.ts | 2 +- test-suites/test-lp/upgradeability.spec.ts | 18 +-- 17 files changed, 368 insertions(+), 347 deletions(-) diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index 466a5abf..006e0d74 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -95,7 +95,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const aaveAdmin = await deployer.getAddress(); const mockTokens = await deployAllMockTokens(deployer); - + console.log("Deployed mocks"); const addressesProvider = await deployLendingPoolAddressesProvider(AaveConfig.MarketId); await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin)); @@ -165,33 +165,33 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { REN: mockTokens.REN.address, UNI: mockTokens.UNI.address, ENJ: mockTokens.ENJ.address, - LpDAI: mockTokens.LpDAI.address, - LpUSDC: mockTokens.LpUSDC.address, - LpUSDT: mockTokens.LpUSDT.address, - LpWBTC: mockTokens.LpWBTC.address, - LpWETH: mockTokens.LpWETH.address, - LpUniDAIWETH: mockTokens.LpUniDAIWETH.address, - LpUniWBTCWETH: mockTokens.LpUniWBTCWETH.address, - LpUniAAVEWETH: mockTokens.LpUniAAVEWETH.address, - LpUniBATWETH: mockTokens.LpUniBATWETH.address, - LpUniUSDCDAI: mockTokens.LpUniUSDCDAI.address, - LpUniCRVWETH: mockTokens.LpUniCRVWETH.address, - LpUniLINKWETH: mockTokens.LpUniLINKWETH.address, - LpUniMKRWETH: mockTokens.LpUniMKRWETH.address, - LpUniRENWETH: mockTokens.LpUniRENWETH.address, - LpUniSNXWETH: mockTokens.LpUniSNXWETH.address, - LpUniUNIWETH: mockTokens.LpUniUNIWETH.address, - LpUniUSDCWETH: mockTokens.LpUniUSDCWETH.address, - LpUniWBTCUSDC: mockTokens.LpUniWBTCUSDC.address, - LpUniYFIWETH: mockTokens.LpUniYFIWETH.address, - LpBalWBTCWETH: mockTokens.LpBalWBTCWETH.address, + // DAI: mockTokens.LpDAI.address, + // USDC: mockTokens.LpUSDC.address, + // USDT: mockTokens.LpUSDT.address, + // WBTC: mockTokens.LpWBTC.address, + // WETH: mockTokens.LpWETH.address, + UniDAIWETH: mockTokens.UniDAIWETH.address, + UniWBTCWETH: mockTokens.UniWBTCWETH.address, + UniAAVEWETH: mockTokens.UniAAVEWETH.address, + UniBATWETH: mockTokens.UniBATWETH.address, + UniUSDCDAI: mockTokens.UniUSDCDAI.address, + UniCRVWETH: mockTokens.UniCRVWETH.address, + UniLINKWETH: mockTokens.UniLINKWETH.address, + UniMKRWETH: mockTokens.UniMKRWETH.address, + UniRENWETH: mockTokens.UniRENWETH.address, + UniSNXWETH: mockTokens.UniSNXWETH.address, + UniUNIWETH: mockTokens.UniUNIWETH.address, + UniUSDCWETH: mockTokens.UniUSDCWETH.address, + UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, + UniYFIWETH: mockTokens.UniYFIWETH.address, + BptWBTCWETH: mockTokens.BptWBTCWETH.address, USD: USD_ADDRESS, }, fallbackOracle ); const mockAggregators = await deployAllMockAggregators(MOCK_CHAINLINK_AGGREGATORS_PRICES); - + console.log("Mock aggs deployed"); const allTokenAddresses = Object.entries(mockTokens).reduce( (accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, tokenContract]) => ({ ...accum, @@ -237,16 +237,27 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const config = loadPoolConfig(ConfigNames.Aave); + const { + ATokenNamePrefix, + StableDebtTokenNamePrefix, + VariableDebtTokenNamePrefix, + SymbolPrefix, + } = config; const treasuryAddress = await getTreasuryAddress(config); await initReservesByHelper( reservesParams, allReservesAddresses, + ATokenNamePrefix, + StableDebtTokenNamePrefix, + VariableDebtTokenNamePrefix, + SymbolPrefix, admin, treasuryAddress, ZERO_ADDRESS, false ); + await configureReservesByHelper(reservesParams, allReservesAddresses, testHelpers, admin); const collateralManager = await deployLendingPoolCollateralManager(); diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-lp/__setup.spec.ts index d38df0f9..09c02efc 100644 --- a/test-suites/test-lp/__setup.spec.ts +++ b/test-suites/test-lp/__setup.spec.ts @@ -66,7 +66,7 @@ const deployAllMockTokens = async (deployer: Signer) => { const lpConfigData = getReservesConfigByPool(AavePools.lp); for (const tokenSymbol of Object.keys(TokenContractId)) { - if (tokenSymbol === 'LpWETH') { + if (tokenSymbol === 'WETH') { tokens[tokenSymbol] = await deployWETHMocked(); await registerContractInJsonDb('WETH', tokens[tokenSymbol]); continue; @@ -165,26 +165,26 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { REN: mockTokens.REN.address, UNI: mockTokens.UNI.address, ENJ: mockTokens.ENJ.address, - LpDAI: mockTokens.LpDAI.address, - LpUSDC: mockTokens.LpUSDC.address, - LpUSDT: mockTokens.LpUSDT.address, - LpWBTC: mockTokens.LpWBTC.address, - LpWETH: mockTokens.LpWETH.address, - LpUniDAIWETH: mockTokens.LpUniDAIWETH.address, - LpUniWBTCWETH: mockTokens.LpUniWBTCWETH.address, - LpUniAAVEWETH: mockTokens.LpUniAAVEWETH.address, - LpUniBATWETH: mockTokens.LpUniBATWETH.address, - LpUniUSDCDAI: mockTokens.LpUniUSDCDAI.address, - LpUniCRVWETH: mockTokens.LpUniCRVWETH.address, - LpUniLINKWETH: mockTokens.LpUniLINKWETH.address, - LpUniMKRWETH: mockTokens.LpUniMKRWETH.address, - LpUniRENWETH: mockTokens.LpUniRENWETH.address, - LpUniSNXWETH: mockTokens.LpUniSNXWETH.address, - LpUniUNIWETH: mockTokens.LpUniUNIWETH.address, - LpUniUSDCWETH: mockTokens.LpUniUSDCWETH.address, - LpUniWBTCUSDC: mockTokens.LpUniWBTCUSDC.address, - LpUniYFIWETH: mockTokens.LpUniYFIWETH.address, - LpBalWBTCWETH: mockTokens.LpBalWBTCWETH.address, + // DAI: mockTokens.LpDAI.address, + // USDC: mockTokens.LpUSDC.address, + // USDT: mockTokens.LpUSDT.address, + // WBTC: mockTokens.LpWBTC.address, + // WETH: mockTokens.LpWETH.address, + UniDAIWETH: mockTokens.UniDAIWETH.address, + UniWBTCWETH: mockTokens.UniWBTCWETH.address, + UniAAVEWETH: mockTokens.UniAAVEWETH.address, + UniBATWETH: mockTokens.UniBATWETH.address, + UniUSDCDAI: mockTokens.UniUSDCDAI.address, + UniCRVWETH: mockTokens.UniCRVWETH.address, + UniLINKWETH: mockTokens.UniLINKWETH.address, + UniMKRWETH: mockTokens.UniMKRWETH.address, + UniRENWETH: mockTokens.UniRENWETH.address, + UniSNXWETH: mockTokens.UniSNXWETH.address, + UniUNIWETH: mockTokens.UniUNIWETH.address, + UniUSDCWETH: mockTokens.UniUSDCWETH.address, + UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, + UniYFIWETH: mockTokens.UniYFIWETH.address, + BptWBTCWETH: mockTokens.BptWBTCWETH.address, USD: USD_ADDRESS, }, fallbackOracle @@ -236,12 +236,22 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { console.log('Initialize configuration'); const config = loadPoolConfig(ConfigNames.Lp); - + + const { + ATokenNamePrefix, + StableDebtTokenNamePrefix, + VariableDebtTokenNamePrefix, + SymbolPrefix, + } = config; const treasuryAddress = await getTreasuryAddress(config); await initReservesByHelper( reservesParams, allReservesAddresses, + ATokenNamePrefix, + StableDebtTokenNamePrefix, + VariableDebtTokenNamePrefix, + SymbolPrefix, admin, treasuryAddress, ZERO_ADDRESS, @@ -269,7 +279,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { await deployWalletBalancerProvider(); - await deployWETHGateway([mockTokens.LpWETH.address, lendingPoolAddress]); + await deployWETHGateway([mockTokens.WETH.address, lendingPoolAddress]); console.timeEnd('setup'); }; diff --git a/test-suites/test-lp/atoken-transfer.spec.ts b/test-suites/test-lp/atoken-transfer.spec.ts index df58bbcf..9d1b8359 100644 --- a/test-suites/test-lp/atoken-transfer.spec.ts +++ b/test-suites/test-lp/atoken-transfer.spec.ts @@ -33,7 +33,7 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { const name = await aDai.name(); - expect(name).to.be.equal('Aave interest bearing LpDAI'); + expect(name).to.be.equal('Aave AMM Market DAI'); const fromBalance = await aDai.balanceOf(users[0].address); const toBalance = await aDai.balanceOf(users[1].address); diff --git a/test-suites/test-lp/helpers/make-suite.ts b/test-suites/test-lp/helpers/make-suite.ts index 07d9a54c..c65f0df0 100644 --- a/test-suites/test-lp/helpers/make-suite.ts +++ b/test-suites/test-lp/helpers/make-suite.ts @@ -128,15 +128,15 @@ export async function initializeMakeSuite() { testEnv.helpersContract = await getAaveProtocolDataProvider(); const allTokens = await testEnv.helpersContract.getAllATokens(); - const aDaiAddress = allTokens.find((aToken) => aToken.symbol === 'aLpDAI')?.tokenAddress; + const aDaiAddress = allTokens.find((aToken) => aToken.symbol === 'aAmmDAI')?.tokenAddress; - const aWEthAddress = allTokens.find((aToken) => aToken.symbol === 'aLpWETH')?.tokenAddress; + const aWEthAddress = allTokens.find((aToken) => aToken.symbol === 'aAmmWETH')?.tokenAddress; const reservesTokens = await testEnv.helpersContract.getAllReservesTokens(); - const daiAddress = reservesTokens.find((token) => token.symbol === 'LpDAI')?.tokenAddress; - const usdcAddress = reservesTokens.find((token) => token.symbol === 'LpUSDC')?.tokenAddress; - const aaveAddress = reservesTokens.find((token) => token.symbol === 'LpUniAAVEWETH')?.tokenAddress; + const daiAddress = reservesTokens.find((token) => token.symbol === 'DAI')?.tokenAddress; + const usdcAddress = reservesTokens.find((token) => token.symbol === 'USDC')?.tokenAddress; + const aaveAddress = reservesTokens.find((token) => token.symbol === 'UniAAVEWETH')?.tokenAddress; const wethAddress = reservesTokens.find((token) => token.symbol === 'WETH')?.tokenAddress; if (!aDaiAddress || !aWEthAddress) { diff --git a/test-suites/test-lp/helpers/scenarios/borrow-negatives.json b/test-suites/test-lp/helpers/scenarios/borrow-negatives.json index 4ae81f1f..03f4d005 100644 --- a/test-suites/test-lp/helpers/scenarios/borrow-negatives.json +++ b/test-suites/test-lp/helpers/scenarios/borrow-negatives.json @@ -3,12 +3,12 @@ "description": "Test cases for the deposit function.", "stories": [ { - "description": "User 0 deposits 1000 LPDAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 LPDAI with rate mode NONE (revert expected)", + "description": "User 0 deposits 1000 DAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 DAI with rate mode NONE (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -60,7 +60,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "none", "user": "1" @@ -71,12 +71,12 @@ ] }, { - "description": "User 0 deposits 1000 LPDAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 LPDAI with an invalid rate mode (revert expected)", + "description": "User 0 deposits 1000 DAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 DAI with an invalid rate mode (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -85,7 +85,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -93,7 +93,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -128,7 +128,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "invalid", "user": "1" diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json b/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json index a1402942..6cebf5b5 100644 --- a/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json +++ b/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json @@ -3,12 +3,12 @@ "description": "Test cases for the borrow function, stable mode.", "stories": [ { - "description": "User 0 deposits 1000 LPDAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 LPDAI at stable rate (revert expected)", + "description": "User 0 deposits 1000 DAI, user 1 deposits 1 WETH as collateral and tries to borrow 100 DAI at stable rate (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -61,7 +61,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "stable", "user": "1", @@ -72,12 +72,12 @@ ] }, { - "description": "User 1 tries to borrow the rest of the LPDAI liquidity (revert expected)", + "description": "User 1 tries to borrow the rest of the DAI liquidity (revert expected)", "actions": [ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "900", "borrowRateMode": "stable", "user": "1" @@ -88,12 +88,12 @@ ] }, { - "description": "User 1 tries to borrow 100 LPDAI at variable", + "description": "User 1 tries to borrow 100 DAI at variable", "actions": [ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "variable", "user": "1" @@ -103,12 +103,12 @@ ] }, { - "description": "User 1 tries to borrow the rest of the LPDAI liquidity at stable (revert expected)", + "description": "User 1 tries to borrow the rest of the DAI liquidity at stable (revert expected)", "actions": [ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "900", "borrowRateMode": "stable", "user": "1" @@ -119,13 +119,13 @@ ] }, { - "description": "User 1 repays half of the LPDAI borrow at stable after one year (revert expected)", + "description": "User 1 repays half of the DAI borrow at stable after one year (revert expected)", "actions": [ { "name": "mint", - "description": "Mint 10 LPDAI to cover the interest", + "description": "Mint 10 DAI to cover the interest", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "10", "user": "1" }, @@ -134,7 +134,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1" }, "expected": "success" @@ -142,7 +142,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "50", "user": "1", "onBehalfOf": "1", @@ -153,12 +153,12 @@ ] }, { - "description": "User 1 repays half of the variable LPDAI borrow after one year", + "description": "User 1 repays half of the variable DAI borrow after one year", "actions": [ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "50", "user": "1", "onBehalfOf": "1", @@ -169,13 +169,13 @@ ] }, { - "description": "User 1 repays the rest of the LPDAI borrow at stable after one year (revert expected)", + "description": "User 1 repays the rest of the DAI borrow at stable after one year (revert expected)", "actions": [ { "name": "mint", - "description": "Mint 15 LPDAI to cover the interest", + "description": "Mint 15 DAI to cover the interest", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "15", "user": "1" }, @@ -184,7 +184,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1" }, "expected": "success" @@ -192,7 +192,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -203,12 +203,12 @@ ] }, { - "description": "User 1 repays the rest of the LPDAI borrow after one year at variable", + "description": "User 1 repays the rest of the DAI borrow after one year at variable", "actions": [ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -219,12 +219,12 @@ ] }, { - "description": "User 0 withdraws the deposited LPDAI plus interest", + "description": "User 0 withdraws the deposited DAI plus interest", "actions": [ { "name": "withdraw", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "0" }, @@ -233,12 +233,12 @@ ] }, { - "description": "User 1 deposits 1000 LPDAI, user 2 tries to borrow 1000 LPDAI at a stable rate without any collateral (revert expected) User 1 withdrawws", + "description": "User 1 deposits 1000 DAI, user 2 tries to borrow 1000 DAI at a stable rate without any collateral (revert expected) User 1 withdrawws", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "1" }, @@ -247,7 +247,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1" }, "expected": "success" @@ -255,7 +255,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "1" }, @@ -264,7 +264,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "borrowRateMode": "stable", "user": "2" @@ -275,7 +275,7 @@ { "name": "withdraw", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "1" }, @@ -284,12 +284,12 @@ ] }, { - "description": "User 0 deposits 1000 LPDAI, user 1,2,3,4 deposit 1 WETH each and borrow 100 LPDAI at stable rate (revert expected) user 0 withdraws", + "description": "User 0 deposits 1000 DAI, user 1,2,3,4 deposit 1 WETH each and borrow 100 DAI at stable rate (revert expected) user 0 withdraws", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -298,7 +298,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -306,7 +306,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -341,7 +341,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "stable", "user": "1", @@ -378,7 +378,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "stable", "user": "2", @@ -415,7 +415,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "stable", "user": "3", @@ -452,7 +452,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "stable", "user": "4", @@ -462,9 +462,9 @@ }, { "name": "mint", - "description": "Mint 15 LPDAI to cover the interest", + "description": "Mint 15 DAI to cover the interest", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "15", "user": "1" }, @@ -473,7 +473,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1" }, "expected": "success" @@ -481,7 +481,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -491,9 +491,9 @@ }, { "name": "mint", - "description": "Mint 20 LPDAI to cover the interest", + "description": "Mint 20 DAI to cover the interest", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "20", "user": "2" }, @@ -502,7 +502,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "2" }, "expected": "success" @@ -510,7 +510,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "2", "onBehalfOf": "2", @@ -520,9 +520,9 @@ }, { "name": "mint", - "description": "Mint 30 LPDAI to cover the interest", + "description": "Mint 30 DAI to cover the interest", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "30", "user": "3" }, @@ -531,7 +531,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "3" }, "expected": "success" @@ -539,7 +539,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "3", "onBehalfOf": "3", @@ -549,9 +549,9 @@ }, { "name": "mint", - "description": "Mint 30 LPDAI to cover the interest", + "description": "Mint 30 DAI to cover the interest", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "30", "user": "4" }, @@ -560,7 +560,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "4" }, "expected": "success" @@ -568,7 +568,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "4", "onBehalfOf": "4", @@ -579,7 +579,7 @@ { "name": "withdraw", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "0" }, @@ -588,12 +588,12 @@ ] }, { - "description": "User 0 deposits 1000 LPDAI, user 1 deposits 2 WETH and borrow 100 LPDAI at stable rate first (revert expected), then 100 LPDAI at variable rate twice, repays everything. User 0 withdraws", + "description": "User 0 deposits 1000 DAI, user 1 deposits 2 WETH and borrow 100 DAI at stable rate first (revert expected), then 100 DAI at variable rate twice, repays everything. User 0 withdraws", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -602,7 +602,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -610,7 +610,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -645,7 +645,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "stable", "user": "1", @@ -656,7 +656,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "variable", "user": "1", @@ -667,7 +667,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "variable", "user": "1", @@ -677,9 +677,9 @@ }, { "name": "mint", - "description": "Mint 50 LPDAI to cover the interest", + "description": "Mint 50 DAI to cover the interest", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "50", "user": "1" }, @@ -688,7 +688,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1" }, "expected": "success" @@ -696,7 +696,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -707,7 +707,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -718,7 +718,7 @@ { "name": "withdraw", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "0" }, diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json b/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json index 39461dfc..ccde9089 100644 --- a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json +++ b/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json @@ -3,12 +3,12 @@ "description": "Test cases for the borrow function, variable mode.", "stories": [ { - "description": "User 2 deposits 1 LPDAI to account for rounding errors", + "description": "User 2 deposits 1 DAI to account for rounding errors", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1", "user": "2" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "2" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1", "user": "2" }, @@ -34,12 +34,12 @@ ] }, { - "description": "User 0 deposits 1000 LPDAI, user 1 deposits 1 WETH as collateral and borrows 100 LPDAI at variable rate", + "description": "User 0 deposits 1000 DAI, user 1 deposits 1 WETH as collateral and borrows 100 DAI at variable rate", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -48,7 +48,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -56,7 +56,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -91,7 +91,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "variable", "user": "1", @@ -102,12 +102,12 @@ ] }, { - "description": "User 1 tries to borrow the rest of the LPDAI liquidity (revert expected)", + "description": "User 1 tries to borrow the rest of the DAI liquidity (revert expected)", "actions": [ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "900", "borrowRateMode": "variable", "user": "1" @@ -118,12 +118,12 @@ ] }, { - "description": "User 1 tries to repay 0 LPDAI (revert expected)", + "description": "User 1 tries to repay 0 DAI (revert expected)", "actions": [ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "0", "user": "1", "onBehalfOf": "1" @@ -134,12 +134,12 @@ ] }, { - "description": "User 1 repays a small amount of LPDAI, enough to cover a small part of the interest", + "description": "User 1 repays a small amount of DAI, enough to cover a small part of the interest", "actions": [ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1" }, "expected": "success" @@ -147,7 +147,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1.25", "user": "1", "onBehalfOf": "1", @@ -158,13 +158,13 @@ ] }, { - "description": "User 1 repays the LPDAI borrow after one year", + "description": "User 1 repays the DAI borrow after one year", "actions": [ { "name": "mint", - "description": "Mint 10 LPDAI to cover the interest", + "description": "Mint 10 DAI to cover the interest", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "10", "user": "1" }, @@ -173,7 +173,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -184,12 +184,12 @@ ] }, { - "description": "User 0 withdraws the deposited LPDAI plus interest", + "description": "User 0 withdraws the deposited DAI plus interest", "actions": [ { "name": "withdraw", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "0" }, @@ -243,7 +243,7 @@ ] }, { - "description": "User 0 deposits 1 WETH, user 1 deposits 100 LPUNILINKWETH as collateral and borrows 0.5 WETH at variable rate", + "description": "User 0 deposits 1 WETH, user 1 deposits 100 UNILINKWETH as collateral and borrows 0.5 WETH at variable rate", "actions": [ { "name": "mint", @@ -274,7 +274,7 @@ { "name": "mint", "args": { - "reserve": "LPUNILINKWETH", + "reserve": "UNILINKWETH", "amount": "100", "user": "1" }, @@ -283,7 +283,7 @@ { "name": "approve", "args": { - "reserve": "LPUNILINKWETH", + "reserve": "UNILINKWETH", "user": "1" }, "expected": "success" @@ -292,7 +292,7 @@ { "name": "deposit", "args": { - "reserve": "LPUNILINKWETH", + "reserve": "UNILINKWETH", "amount": "100", "user": "1" }, @@ -431,7 +431,7 @@ { "name": "withdraw", "args": { - "reserve": "LPUNILINKWETH", + "reserve": "UNILINKWETH", "amount": "-1", "user": "1" }, @@ -441,12 +441,12 @@ }, { - "description": "User 2 deposits 1 LPUSDC to account for rounding errors", + "description": "User 2 deposits 1 USDC to account for rounding errors", "actions": [ { "name": "mint", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1", "user": "2" }, @@ -455,7 +455,7 @@ { "name": "approve", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "2" }, "expected": "success" @@ -463,7 +463,7 @@ { "name": "deposit", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1", "user": "2" }, @@ -472,12 +472,12 @@ ] }, { - "description": "User 0 deposits 1000 LPUSDC, user 1 deposits 1 WETH as collateral and borrows 100 LPUSDC at variable rate", + "description": "User 0 deposits 1000 USDC, user 1 deposits 1 WETH as collateral and borrows 100 USDC at variable rate", "actions": [ { "name": "mint", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "0" }, @@ -486,7 +486,7 @@ { "name": "approve", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "0" }, "expected": "success" @@ -494,7 +494,7 @@ { "name": "deposit", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "0" }, @@ -529,7 +529,7 @@ { "name": "borrow", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "100", "borrowRateMode": "variable", "user": "1", @@ -540,12 +540,12 @@ ] }, { - "description": "User 1 tries to borrow the rest of the LPUSDC liquidity (revert expected)", + "description": "User 1 tries to borrow the rest of the USDC liquidity (revert expected)", "actions": [ { "name": "borrow", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "900", "borrowRateMode": "variable", "user": "1" @@ -556,13 +556,13 @@ ] }, { - "description": "User 1 repays the LPUSDC borrow after one year", + "description": "User 1 repays the USDC borrow after one year", "actions": [ { "name": "mint", - "description": "Mint 10 LPUSDC to cover the interest", + "description": "Mint 10 USDC to cover the interest", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "10", "user": "1" }, @@ -571,7 +571,7 @@ { "name": "approve", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "1" }, "expected": "success" @@ -579,7 +579,7 @@ { "name": "repay", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -590,12 +590,12 @@ ] }, { - "description": "User 0 withdraws the deposited LPUSDC plus interest", + "description": "User 0 withdraws the deposited USDC plus interest", "actions": [ { "name": "withdraw", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "-1", "user": "0" }, @@ -618,12 +618,12 @@ ] }, { - "description": "User 1 deposits 1000 LPDAI, user 3 tries to borrow 1000 LPDAI without any collateral (revert expected)", + "description": "User 1 deposits 1000 DAI, user 3 tries to borrow 1000 DAI without any collateral (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "1" }, @@ -632,7 +632,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1" }, "expected": "success" @@ -640,7 +640,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "1" }, @@ -649,7 +649,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "borrowRateMode": "variable", "user": "3" @@ -660,7 +660,7 @@ ] }, { - "description": "user 3 deposits 0.1 WETH collateral to borrow 100 LPDAI; 0.1 WETH is not enough to borrow 100 LPDAI (revert expected)", + "description": "user 3 deposits 0.1 WETH collateral to borrow 100 DAI; 0.1 WETH is not enough to borrow 100 DAI (revert expected)", "actions": [ { "name": "mint", @@ -691,7 +691,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "variable", "user": "3" @@ -716,12 +716,12 @@ ] }, { - "description": "User 1 deposits 1000 LPUSDC, user 3 tries to borrow 1000 LPUSDC without any collateral (revert expected)", + "description": "User 1 deposits 1000 USDC, user 3 tries to borrow 1000 USDC without any collateral (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "1" }, @@ -730,7 +730,7 @@ { "name": "approve", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "1" }, "expected": "success" @@ -738,7 +738,7 @@ { "name": "deposit", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "1" }, @@ -747,7 +747,7 @@ { "name": "borrow", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "borrowRateMode": "variable", "user": "3" @@ -758,7 +758,7 @@ ] }, { - "description": "user 3 deposits 0.1 WETH collateral to borrow 100 LPUSDC; 0.1 WETH is not enough to borrow 100 LPUSDC (revert expected)", + "description": "user 3 deposits 0.1 WETH collateral to borrow 100 USDC; 0.1 WETH is not enough to borrow 100 USDC (revert expected)", "actions": [ { "name": "mint", @@ -789,7 +789,7 @@ { "name": "borrow", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "100", "borrowRateMode": "variable", "user": "3" @@ -814,12 +814,12 @@ ] }, { - "description": "User 0 deposits 1000 LPDAI, user 6 deposits 2 WETH and borrow 100 LPDAI at variable rate first, then 100 LPDAI at stable rate (revert expected), then 100 LPDAI at variable again, repays everything. User 0 withdraws", + "description": "User 0 deposits 1000 DAI, user 6 deposits 2 WETH and borrow 100 DAI at variable rate first, then 100 DAI at stable rate (revert expected), then 100 DAI at variable again, repays everything. User 0 withdraws", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -828,7 +828,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -836,7 +836,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -871,7 +871,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "variable", "user": "6", @@ -882,7 +882,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "stable", "user": "6", @@ -893,7 +893,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "variable", "user": "6", @@ -903,9 +903,9 @@ }, { "name": "mint", - "description": "Mint 50 LPDAI to cover the interest", + "description": "Mint 50 DAI to cover the interest", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "50", "user": "6" }, @@ -914,7 +914,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "6" }, "expected": "success" @@ -922,7 +922,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "6", "onBehalfOf": "6", @@ -933,7 +933,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "6", "onBehalfOf": "6", @@ -944,7 +944,7 @@ { "name": "withdraw", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "0" }, diff --git a/test-suites/test-lp/helpers/scenarios/credit-delegation.json b/test-suites/test-lp/helpers/scenarios/credit-delegation.json index 46437c40..8798083b 100644 --- a/test-suites/test-lp/helpers/scenarios/credit-delegation.json +++ b/test-suites/test-lp/helpers/scenarios/credit-delegation.json @@ -3,7 +3,7 @@ "description": "Test cases for the credit delegation related functions.", "stories": [ { - "description": "User 3 deposits 1000 WETH. User 0 deposits 1000 LPDAI, user 0 delegates borrowing of 1 WETH on variable to user 4, user 4 borrows 1 WETH variable on behalf of user 0", + "description": "User 3 deposits 1000 WETH. User 0 deposits 1000 DAI, user 0 delegates borrowing of 1 WETH on variable to user 4, user 4 borrows 1 WETH variable on behalf of user 0", "actions": [ { "name": "mint", @@ -34,7 +34,7 @@ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -43,7 +43,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -51,7 +51,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, diff --git a/test-suites/test-lp/helpers/scenarios/deposit.json b/test-suites/test-lp/helpers/scenarios/deposit.json index 960011e3..b4b73879 100644 --- a/test-suites/test-lp/helpers/scenarios/deposit.json +++ b/test-suites/test-lp/helpers/scenarios/deposit.json @@ -3,12 +3,12 @@ "description": "Test cases for the deposit function.", "stories": [ { - "description": "User 0 Deposits 1000 LPDAI in an empty reserve", + "description": "User 0 Deposits 1000 DAI in an empty reserve", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -34,12 +34,12 @@ ] }, { - "description": "User 1 deposits 1000 LPDAI after user 0", + "description": "User 1 deposits 1000 DAI after user 0", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "1" }, @@ -48,7 +48,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1" }, "expected": "success" @@ -56,7 +56,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "1" }, @@ -65,12 +65,12 @@ ] }, { - "description": "User 0 deposits 1000 LPUSDC in an empty reserve", + "description": "User 0 deposits 1000 USDC in an empty reserve", "actions": [ { "name": "mint", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "0" }, @@ -79,7 +79,7 @@ { "name": "approve", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "0" }, "expected": "success" @@ -87,7 +87,7 @@ { "name": "deposit", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "0" }, @@ -96,12 +96,12 @@ ] }, { - "description": "User 1 deposits 1000 LPUSDC after user 0", + "description": "User 1 deposits 1000 USDC after user 0", "actions": [ { "name": "mint", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "1" }, @@ -110,7 +110,7 @@ { "name": "approve", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "1" }, "expected": "success" @@ -118,7 +118,7 @@ { "name": "deposit", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "1" }, @@ -214,12 +214,12 @@ ] }, { - "description": "User 1 deposits 0 LPDAI", + "description": "User 1 deposits 0 DAI", "actions": [ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "0", "user": "1" }, @@ -229,12 +229,12 @@ ] }, { - "description": "User 1 deposits 100 LPDAI on behalf of user 2, user 2 tries to borrow 0.1 WETH", + "description": "User 1 deposits 100 DAI on behalf of user 2, user 2 tries to borrow 0.1 WETH", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "user": "1" }, @@ -243,7 +243,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "user": "1", "onBehalfOf": "2" diff --git a/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json b/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json index 21c09510..8e4f17b6 100644 --- a/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json +++ b/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json @@ -8,7 +8,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "0", "target": "1" }, @@ -18,12 +18,12 @@ ] }, { - "description": "User 0 deposits 1000 LPUSDC, user 1 deposits 7 WETH, borrows 250 LPUSDC at a variable rate, user 0 rebalances user 1 (revert expected)", + "description": "User 0 deposits 1000 USDC, user 1 deposits 7 WETH, borrows 250 USDC at a variable rate, user 0 rebalances user 1 (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "0" }, @@ -32,7 +32,7 @@ { "name": "approve", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "0" }, "expected": "success" @@ -40,7 +40,7 @@ { "name": "deposit", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "0" }, @@ -75,7 +75,7 @@ { "name": "borrow", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "250", "borrowRateMode": "variable", "user": "1" @@ -85,7 +85,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "0", "target": "1" }, @@ -100,7 +100,7 @@ { "name": "borrow", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "200", "borrowRateMode": "variable", "user": "1" @@ -110,7 +110,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "0", "target": "1" }, @@ -125,7 +125,7 @@ { "name": "borrow", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "200", "borrowRateMode": "variable", "user": "1" @@ -135,7 +135,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "0", "target": "1" }, @@ -150,7 +150,7 @@ { "name": "borrow", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "280", "borrowRateMode": "variable", "user": "1" @@ -160,7 +160,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "0", "target": "1" }, @@ -171,12 +171,12 @@ }, { - "description": "User 1 borrows the remaining LPUSDC (usage ratio = 100%) at variable. User 0 rebalances user 1, fails since there are no stable borrows (revert expected)", + "description": "User 1 borrows the remaining USDC (usage ratio = 100%) at variable. User 0 rebalances user 1, fails since there are no stable borrows (revert expected)", "actions": [ { "name": "borrow", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "20", "borrowRateMode": "variable", "user": "1" @@ -186,7 +186,7 @@ { "name": "rebalanceStableBorrowRate", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "0", "target": "1" }, diff --git a/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json b/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json index 49785753..d2c8520a 100644 --- a/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json +++ b/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json @@ -3,12 +3,12 @@ "description": "Test cases for the setUserUseReserveAsCollateral() function.", "stories": [ { - "description": "User 0 Deposits 1000 LPDAI, disables LPDAI as collateral", + "description": "User 0 Deposits 1000 DAI, disables DAI as collateral", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -34,7 +34,7 @@ { "name": "setUseAsCollateral", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0", "useAsCollateral": "false" }, @@ -43,7 +43,7 @@ ] }, { - "description": "User 1 Deposits 2 WETH, disables WETH as collateral, borrows 400 LPDAI (revert expected)", + "description": "User 1 Deposits 2 WETH, disables WETH as collateral, borrows 400 DAI (revert expected)", "actions": [ { "name": "mint", @@ -83,7 +83,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "400", "borrowRateMode": "variable", "user": "1" @@ -94,7 +94,7 @@ ] }, { - "description": "User 1 enables WETH as collateral, borrows 400 LPDAI", + "description": "User 1 enables WETH as collateral, borrows 400 DAI", "actions": [ { "name": "setUseAsCollateral", @@ -108,7 +108,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "400", "borrowRateMode": "variable", "user": "1" @@ -133,12 +133,12 @@ ] }, { - "description": "User 1 Deposits 10 LPUNILINKWETH, disables WETH as collateral. Should revert as 10 LPUNILINKWETH are not enough to cover the debt (revert expected)", + "description": "User 1 Deposits 10 UNILINKWETH, disables WETH as collateral. Should revert as 10 UNILINKWETH are not enough to cover the debt (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "LPUNILINKWETH", + "reserve": "UNILINKWETH", "amount": "10", "user": "1" }, @@ -147,7 +147,7 @@ { "name": "approve", "args": { - "reserve": "LPUNILINKWETH", + "reserve": "UNILINKWETH", "user": "1" }, "expected": "success" @@ -155,7 +155,7 @@ { "name": "deposit", "args": { - "reserve": "LPUNILINKWETH", + "reserve": "UNILINKWETH", "amount": "10", "user": "1" }, @@ -173,12 +173,12 @@ ] }, { - "description": "User 1 Deposits 640 more LPUNILINKWETH (enough to cover the LPDAI debt), disables WETH as collateral", + "description": "User 1 Deposits 640 more UNILINKWETH (enough to cover the DAI debt), disables WETH as collateral", "actions": [ { "name": "mint", "args": { - "reserve": "LPUNILINKWETH", + "reserve": "UNILINKWETH", "amount": "640", "user": "1" }, @@ -187,7 +187,7 @@ { "name": "deposit", "args": { - "reserve": "LPUNILINKWETH", + "reserve": "UNILINKWETH", "amount": "640", "user": "1" }, @@ -205,12 +205,12 @@ ] }, { - "description": "User 1 disables LPUNILINKWETH as collateral (revert expected)", + "description": "User 1 disables UNILINKWETH as collateral (revert expected)", "actions": [ { "name": "setUseAsCollateral", "args": { - "reserve": "LPUNILINKWETH", + "reserve": "UNILINKWETH", "user": "1", "useAsCollateral": "false" }, diff --git a/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json b/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json index 82b44e83..17f9dfe3 100644 --- a/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json +++ b/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json @@ -8,7 +8,7 @@ { "name": "swapBorrowRateMode", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1", "borrowRateMode": "variable" }, @@ -23,7 +23,7 @@ { "name": "swapBorrowRateMode", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1", "borrowRateMode": "stable" }, @@ -33,12 +33,12 @@ ] }, { - "description": "User 0 deposits 1000 LPDAI, user 1 deposits 2 WETH as collateral, borrows 100 LPDAI at variable rate and swaps to stable after one year, fails because stable borrowing is disabled (revert expected)", + "description": "User 0 deposits 1000 DAI, user 1 deposits 2 WETH as collateral, borrows 100 DAI at variable rate and swaps to stable after one year, fails because stable borrowing is disabled (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -47,7 +47,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -55,7 +55,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -90,7 +90,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "variable", "user": "1", @@ -101,7 +101,7 @@ { "name": "swapBorrowRateMode", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1", "borrowRateMode": "variable" }, @@ -110,12 +110,12 @@ ] }, { - "description": "User 1 borrows another 100 LPDAI at stable (revert expected), and swaps back to variable after one year (revert expected), repays the loan", + "description": "User 1 borrows another 100 DAI at stable (revert expected), and swaps back to variable after one year (revert expected), repays the loan", "actions": [ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "stable", "user": "1", @@ -126,7 +126,7 @@ { "name": "swapBorrowRateMode", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1", "borrowRateMode": "stable" }, @@ -134,9 +134,9 @@ }, { "name": "mint", - "description": "Mint 50 LPDAI to cover the interest", + "description": "Mint 50 DAI to cover the interest", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "50", "user": "1" }, @@ -145,7 +145,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1" }, "expected": "success" @@ -153,7 +153,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "1", "onBehalfOf": "1", @@ -164,12 +164,12 @@ ] }, { - "description": "User 1 borrows another 100 LPDAI at variable, and tries to swap to stable after one year (revert expected), repays the loan", + "description": "User 1 borrows another 100 DAI at variable, and tries to swap to stable after one year (revert expected), repays the loan", "actions": [ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "borrowRateMode": "variable", "user": "1", @@ -180,7 +180,7 @@ { "name": "swapBorrowRateMode", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1", "borrowRateMode": "stable" }, @@ -188,9 +188,9 @@ }, { "name": "mint", - "description": "Mint 50 LPDAI to cover the interest", + "description": "Mint 50 DAI to cover the interest", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "50", "user": "1" }, @@ -199,7 +199,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1" }, "expected": "success" @@ -207,7 +207,7 @@ { "name": "repay", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "1", "onBehalfOf": "1", diff --git a/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json b/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json index e282e65c..cf50812d 100644 --- a/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json +++ b/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json @@ -3,12 +3,12 @@ "description": "Redeem function.", "stories": [ { - "description": "Users 0 Deposits 1000 LPDAI and tries to redeem 0 LPDAI (revert expected)", + "description": "Users 0 Deposits 1000 DAI and tries to redeem 0 DAI (revert expected)", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -35,7 +35,7 @@ { "name": "withdraw", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "0", "user": "0" }, @@ -45,12 +45,12 @@ ] }, { - "description": "Users 0 tries to redeem 1100 LPDAI from the 1000 LPDAI deposited (revert expected)", + "description": "Users 0 tries to redeem 1100 DAI from the 1000 DAI deposited (revert expected)", "actions": [ { "name": "withdraw", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1100", "user": "0" }, @@ -60,7 +60,7 @@ ] }, { - "description": "Users 1 deposits 1 WETH, borrows 100 LPDAI stable (revert expected), redeems the 1 WETH deposited", + "description": "Users 1 deposits 1 WETH, borrows 100 DAI stable (revert expected), redeems the 1 WETH deposited", "actions": [ { "name": "mint", @@ -91,7 +91,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "user": "1", "borrowRateMode": "stable" @@ -110,7 +110,7 @@ ] }, { - "description": "Users 1 deposits 1 WETH, borrows 100 LPDAI at variable rate, tries to redeem the 1 WETH deposited (revert expected)", + "description": "Users 1 deposits 1 WETH, borrows 100 DAI at variable rate, tries to redeem the 1 WETH deposited (revert expected)", "actions": [ { "name": "mint", @@ -141,7 +141,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "user": "1", "borrowRateMode": "variable" diff --git a/test-suites/test-lp/helpers/scenarios/withdraw.json b/test-suites/test-lp/helpers/scenarios/withdraw.json index ac72b2c6..d3b69908 100644 --- a/test-suites/test-lp/helpers/scenarios/withdraw.json +++ b/test-suites/test-lp/helpers/scenarios/withdraw.json @@ -3,12 +3,12 @@ "description": "withdraw function.", "stories": [ { - "description": "User 0 Deposits 1000 LPDAI in an empty reserve", + "description": "User 0 Deposits 1000 DAI in an empty reserve", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -17,7 +17,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "0" }, "expected": "success" @@ -25,7 +25,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -34,12 +34,12 @@ ] }, { - "description": "User 0 withdraws half of the deposited LPDAI", + "description": "User 0 withdraws half of the deposited DAI", "actions": [ { "name": "withdraw", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "500", "user": "0" }, @@ -48,12 +48,12 @@ ] }, { - "description": "User 0 withdraws remaining half of the deposited LPDAI", + "description": "User 0 withdraws remaining half of the deposited DAI", "actions": [ { "name": "withdraw", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "0" }, @@ -62,12 +62,12 @@ ] }, { - "description": "User 0 Deposits 1000 LPUSDC in an empty reserve", + "description": "User 0 Deposits 1000 USDC in an empty reserve", "actions": [ { "name": "mint", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "0" }, @@ -76,7 +76,7 @@ { "name": "approve", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "0" }, "expected": "success" @@ -84,7 +84,7 @@ { "name": "deposit", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "0" }, @@ -93,12 +93,12 @@ ] }, { - "description": "User 0 withdraws half of the deposited LPUSDC", + "description": "User 0 withdraws half of the deposited USDC", "actions": [ { "name": "withdraw", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "500", "user": "0" }, @@ -107,12 +107,12 @@ ] }, { - "description": "User 0 withdraws remaining half of the deposited LPUSDC", + "description": "User 0 withdraws remaining half of the deposited USDC", "actions": [ { "name": "withdraw", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "-1", "user": "0" }, @@ -180,12 +180,12 @@ ] }, { - "description": "Users 0 and 1 Deposit 1000 LPDAI, both withdraw", + "description": "Users 0 and 1 Deposit 1000 DAI, both withdraw", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "1" }, @@ -194,7 +194,7 @@ { "name": "approve", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "user": "1" }, "expected": "success" @@ -202,7 +202,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -211,7 +211,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "1" }, @@ -220,7 +220,7 @@ { "name": "withdraw", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "0" }, @@ -229,7 +229,7 @@ { "name": "withdraw", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "-1", "user": "1" }, @@ -238,12 +238,12 @@ ] }, { - "description": "Users 0 deposits 1000 LPDAI, user 1 Deposit 1000 LPUSDC and 1 WETH, borrows 100 LPDAI at stable rate (revert expected). User 1 tries to withdraw all the LPUSDC", + "description": "Users 0 deposits 1000 DAI, user 1 Deposit 1000 USDC and 1 WETH, borrows 100 DAI at stable rate (revert expected). User 1 tries to withdraw all the USDC", "actions": [ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -252,7 +252,7 @@ { "name": "mint", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "1" }, @@ -261,7 +261,7 @@ { "name": "approve", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "1" }, "expected": "success" @@ -269,7 +269,7 @@ { "name": "deposit", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "1" }, @@ -304,7 +304,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "user": "1", "borrowRateMode": "stable" @@ -314,7 +314,7 @@ { "name": "withdraw", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "-1", "user": "1" }, @@ -323,12 +323,12 @@ ] }, { - "description": "Users 0 deposits 1000 LPDAI, user 1 Deposit 1000 LPUSDC and 1 WETH, borrows 100 LPDAI at variable rate. User 1 tries to withdraw all the LPUSDC", + "description": "Users 0 deposits 1000 DAI, user 1 Deposit 1000 USDC and 1 WETH, borrows 100 DAI at variable rate. User 1 tries to withdraw all the USDC", "actions": [ { "name": "mint", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -337,7 +337,7 @@ { "name": "deposit", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "1000", "user": "0" }, @@ -346,7 +346,7 @@ { "name": "mint", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "10000", "user": "1" }, @@ -355,7 +355,7 @@ { "name": "approve", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "user": "1" }, "expected": "success" @@ -363,7 +363,7 @@ { "name": "deposit", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "1000", "user": "1" }, @@ -398,7 +398,7 @@ { "name": "borrow", "args": { - "reserve": "LPDAI", + "reserve": "DAI", "amount": "100", "user": "1", "borrowRateMode": "variable" @@ -408,7 +408,7 @@ { "name": "withdraw", "args": { - "reserve": "LPUSDC", + "reserve": "USDC", "amount": "-1", "user": "1" }, diff --git a/test-suites/test-lp/helpers/utils/calculations.ts b/test-suites/test-lp/helpers/utils/calculations.ts index 1a801cc1..e1574656 100644 --- a/test-suites/test-lp/helpers/utils/calculations.ts +++ b/test-suites/test-lp/helpers/utils/calculations.ts @@ -1238,9 +1238,9 @@ export const calcExpectedInterestRates = ( const { reservesParams } = configuration; // Fixes WETH - LpWETH mock token symbol mismatch - if(reserveSymbol === 'WETH') { - reserveSymbol = 'LpWETH'; - } + // if(reserveSymbol === 'WETH') { + // reserveSymbol = 'LpWETH'; + // } const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol); const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[ reserveIndex diff --git a/test-suites/test-lp/stable-token.spec.ts b/test-suites/test-lp/stable-token.spec.ts index 58884018..d3c75fc6 100644 --- a/test-suites/test-lp/stable-token.spec.ts +++ b/test-suites/test-lp/stable-token.spec.ts @@ -29,7 +29,7 @@ makeSuite('Stable debt token tests', (testEnv: TestEnv) => { const name = await stableDebtContract.name(); - expect(name).to.be.equal('Aave stable debt bearing LpDAI'); + expect(name).to.be.equal('Aave AMM Market stable debt DAI'); await expect(stableDebtContract.burn(deployer.address, '1')).to.be.revertedWith( CT_CALLER_MUST_BE_LENDING_POOL ); diff --git a/test-suites/test-lp/upgradeability.spec.ts b/test-suites/test-lp/upgradeability.spec.ts index 53050b48..bbe5799b 100644 --- a/test-suites/test-lp/upgradeability.spec.ts +++ b/test-suites/test-lp/upgradeability.spec.ts @@ -32,24 +32,24 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { dai.address, ZERO_ADDRESS, ZERO_ADDRESS, - 'Aave Interest bearing LpDAI updated', - 'aUniDAI', + 'Aave AMM Market DAI updated', + 'aAmmDAI', ]); const stableDebtTokenInstance = await deployMockStableDebtToken([ pool.address, dai.address, ZERO_ADDRESS, - 'Aave stable debt bearing LpDAI updated', - 'stableDebtUniDAI', + 'Aave AMM Market stable debt DAI updated', + 'stableDebtAmmDAI', ]); const variableDebtTokenInstance = await deployMockVariableDebtToken([ pool.address, dai.address, ZERO_ADDRESS, - 'Aave variable debt bearing LpDAI updated', - 'variableDebtUniDAI', + 'Aave AMM Market variable debt DAI updated', + 'variableDebtAmmDAI', ]); newATokenAddress = aTokenInstance.address; @@ -108,7 +108,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { const tokenName = await aDai.name(); - expect(tokenName).to.be.eq('Aave Interest bearing LpDAI updated', 'Invalid token name'); + expect(tokenName).to.be.eq('Aave AMM Market DAI updated', 'Invalid token name'); }); it('Tries to update the DAI Stable debt token implementation with a different address than the lendingPoolManager', async () => { @@ -168,7 +168,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { const tokenName = await debtToken.name(); - expect(tokenName).to.be.eq('Aave stable debt bearing LpDAI updated', 'Invalid token name'); + expect(tokenName).to.be.eq('Aave AMM Market stable debt DAI updated', 'Invalid token name'); }); it('Tries to update the DAI variable debt token implementation with a different address than the lendingPoolManager', async () => { @@ -229,6 +229,6 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { const tokenName = await debtToken.name(); - expect(tokenName).to.be.eq('Aave variable debt bearing LpDAI updated', 'Invalid token name'); + expect(tokenName).to.be.eq('Aave AMM Market variable debt DAI updated', 'Invalid token name'); }); }); From 83d92ac1efd41877202624bc3418b637676889a2 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 16:15:59 -0500 Subject: [PATCH 111/219] Updated kovan assets --- markets/lp/index.ts | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/markets/lp/index.ts b/markets/lp/index.ts index 5886bf85..5f66ce18 100644 --- a/markets/lp/index.ts +++ b/markets/lp/index.ts @@ -64,21 +64,21 @@ export const lpConfig: ILpConfiguration = { USDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', WBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', WETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', - UniDAIWETH: '0x7e48b02B21D784e79E17b06988fc150c8b5945df', - UniWBTCWETH: '0x4Fd18882730dc5f945d5049C3f99Ee43CCA1F3d9', - UniAAVEWETH: '0xC173038224d47e11962bb0Bd10e036c573C57dF0', - UniBATWETH: '0xfC482c56A91Cc92019FF6522B2FB76F41B7e2535', - UniUSDCDAI: '0xFD0795980D4c37Fd867228C86A1f7693C9219142', - UniCRVWETH: '0xC7f1899F8B5861d8A3Ce1385194bc130A15C8a74', - UniLINKWETH: '0xCe2355F9249ced9E51ecc35AbB749352C2557D0d', - UniMKRWETH: '0xDCf7A28f4102B7f5813148cCEFb02134648E6F0C', - UniRENWETH: '0xe46C9459833bBa061471DF2a383D27a20FE97E23', - UniSNXWETH: '0xAa5826dea7cfEc02AcB644b24387bE2648feAbB9', - UniUNIWETH: '0xD4C255B5500cFB262EB5F9105Ea546Aa0610A0d3', - UniUSDCWETH: '0x509f6ce2F9718E3dd854cCE1857FabCc59C6dd5e', - UniWBTCUSDC: '0x9D15e3A14926A16C9B285A5c6bd6c9e82d5F8031', - UniYFIWETH: '0xC6Dc783B3C2E2Cbf71791d253f8b4993D40DBf98', - BptWBTCWETH: '0x930087451C5940B28bE556d32a4CF22D5d9754A1', + UniDAIWETH: '0x0C652EeEA3d7D35759ba1E16183F1D89C386C9ea', + UniWBTCWETH: '0x796d562B1dF5b9dc85A4612187B6f29Ed213d960', + UniAAVEWETH: '0x657A7B8b46F35C5C6583AEF43824744B236EF826', + UniBATWETH: '0xf8CEBA8b16579956B3aE4B5D09002a30f873F783', + UniUSDCDAI: '0x8e80b7a7531c276dD1dBEC2f1Cc281c11c859e62', + UniCRVWETH: '0x9c31b7538467bF0b01e6d5fA789e66Ce540a521e', + UniLINKWETH: '0x5Acab7f8B79620ec7127A96E5D8837d2124D5D7c', + UniMKRWETH: '0xB0C6EC5d58ddbF4cd1e419A56a19924E9904e4Dd', + UniRENWETH: '0xcF428637A9f8Af21920Bc0A94fd81071bc790105', + UniSNXWETH: '0xc8F2a0d698f675Ece74042e9fB06ea52b9517521', + UniUNIWETH: '0xcC99A5f95a86d30e3DeF113bCf22f00ecF90D050', + UniUSDCWETH: '0x8C00D2428ed1857E61652aca663323A85E6e76a9', + UniWBTCUSDC: '0x3d35B5F289f55A580e6F85eE22E6a8f57053b966', + UniYFIWETH: '0x5af95ddFACC150a1695A3Fc606459fd0dE57b91f', + BptWBTCWETH: '0x110569E3261bC0934dA637b019f6f1b6F50ec574', }, [EthereumNetwork.ropsten]: { }, From 6d0daf033d882ad67c4eef9620a083f882819047 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 16:44:27 -0500 Subject: [PATCH 112/219] Began adaptation to new networks --- hardhat.config.ts | 30 ++- helpers/types.ts | 6 + markets/aave/commons.ts | 28 +++ markets/aave/index.ts | 2 + markets/lp/commons.ts | 28 +++ markets/lp/index.ts | 2 + markets/matic/commons.ts | 384 +++++++++++++++++++++++++++++++ markets/matic/index.ts | 153 ++++++++++++ markets/matic/rateStrategies.ts | 91 ++++++++ markets/matic/reservesConfigs.ts | 254 ++++++++++++++++++++ 10 files changed, 977 insertions(+), 1 deletion(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 935aa371..ed0fa247 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -18,7 +18,7 @@ import '@tenderly/hardhat-tenderly'; const SKIP_LOAD = process.env.SKIP_LOAD === 'true'; const DEFAULT_BLOCK_GAS_LIMIT = 12450000; const DEFAULT_GAS_MUL = 5; -const DEFAULT_GAS_PRICE = 65000000000; +const DEFAULT_GAS_PRICE = 65 * 1000 * 1000 * 1000; const HARDFORK = 'istanbul'; const INFURA_KEY = process.env.INFURA_KEY || ''; const ALCHEMY_KEY = process.env.ALCHEMY_KEY || ''; @@ -45,6 +45,32 @@ require(`${path.join(__dirname, 'tasks/misc')}/set-bre.ts`); const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number) => { const net = networkName === 'main' ? 'mainnet' : networkName; + if (networkName == 'matic') return { + url: 'https://rpc-mainnet.matic.network', + blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, + gasMultiplier: DEFAULT_GAS_MUL, + gasPrice: DEFAULT_GAS_PRICE, + chainId: networkId, + accounts: { + mnemonic: MNEMONIC, + path: MNEMONIC_PATH, + initialIndex: 0, + count: 20, + }, + } + if (networkName == 'mumbai') return { + url: 'https://rpc-mumbai.maticvigil.com', + blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, + gasMultiplier: DEFAULT_GAS_MUL, + gasPrice: 1 * 1000 * 1000 * 1000, + chainId: networkId, + accounts: { + mnemonic: MNEMONIC, + path: MNEMONIC_PATH, + initialIndex: 0, + count: 20, + }, + } return { url: ALCHEMY_KEY ? `https://eth-${net}.alchemyapi.io/v2/${ALCHEMY_KEY}` @@ -104,6 +130,8 @@ const buidlerConfig: HardhatUserConfig = { ropsten: getCommonNetworkConfig(eEthereumNetwork.ropsten, 3), main: getCommonNetworkConfig(eEthereumNetwork.main, 1), tenderlyMain: getCommonNetworkConfig(eEthereumNetwork.main, 1), + matic: getCommonNetworkConfig(eEthereumNetwork.matic, 137), + mumbai: getCommonNetworkConfig(eEthereumNetwork.mumbai, 80001), hardhat: { hardfork: 'istanbul', blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, diff --git a/helpers/types.ts b/helpers/types.ts index 54c75180..cde24a10 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -12,6 +12,8 @@ export enum eEthereumNetwork { coverage = 'coverage', hardhat = 'hardhat', tenderlyMain = 'tenderlyMain', + matic = 'matic', + mumbai = 'mumbai', } export enum EthereumNetworkNames { @@ -374,6 +376,8 @@ export interface iParamsPerNetwork { [eEthereumNetwork.main]: T; [eEthereumNetwork.hardhat]: T; [eEthereumNetwork.tenderlyMain]: T; + [eEthereumNetwork.mumbai]: T; + [eEthereumNetwork.matic]: T; } export interface iParamsPerPool { @@ -403,6 +407,8 @@ export enum EthereumNetwork { main = 'main', coverage = 'soliditycoverage', tenderlyMain = 'tenderlyMain', + matic = 'matic', + mumbai = 'mumbai', } export interface IProtocolGlobalConfig { diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index f5992dba..5a6df636 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -145,6 +145,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: undefined, [eEthereumNetwork.main]: undefined, [eEthereumNetwork.tenderlyMain]: undefined, + [eEthereumNetwork.mumbai]: undefined, + [eEthereumNetwork.matic]: undefined, }, PoolAdminIndex: 0, EmergencyAdmin: { @@ -155,6 +157,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: undefined, [eEthereumNetwork.main]: undefined, [eEthereumNetwork.tenderlyMain]: undefined, + [eEthereumNetwork.mumbai]: undefined, + [eEthereumNetwork.matic]: undefined, }, EmergencyAdminIndex: 1, ProviderRegistry: { @@ -165,6 +169,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, ProviderRegistryOwner: { [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', @@ -174,6 +180,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, LendingRateOracle: { [eEthereumNetwork.coverage]: '', @@ -183,6 +191,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', [eEthereumNetwork.main]: '',//'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, LendingPoolCollateralManager: { [eEthereumNetwork.coverage]: '', @@ -192,6 +202,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, TokenDistributor: { [eEthereumNetwork.coverage]: '', @@ -201,6 +213,8 @@ export const CommonsConfig: ICommonConfiguration = { [EthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c', [EthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', [EthereumNetwork.tenderlyMain]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, AaveOracle: { [eEthereumNetwork.coverage]: '', @@ -210,6 +224,8 @@ export const CommonsConfig: ICommonConfiguration = { [EthereumNetwork.ropsten]: ZERO_ADDRESS, [EthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, FallbackOracle: { [eEthereumNetwork.coverage]: '', @@ -219,11 +235,15 @@ export const CommonsConfig: ICommonConfiguration = { [EthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d', [EthereumNetwork.main]: ZERO_ADDRESS, [EthereumNetwork.tenderlyMain]: ZERO_ADDRESS, + [eEthereumNetwork.mumbai]: ZERO_ADDRESS, + [eEthereumNetwork.matic]: ZERO_ADDRESS, }, ChainlinkAggregator: { [eEthereumNetwork.coverage]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.buidlerevm]: {}, + [eEthereumNetwork.matic]: {}, + [eEthereumNetwork.mumbai]: {}, [EthereumNetwork.kovan]: { AAVE: '0xd04647B7CB523bb9f26730E9B6dE1174db7591Ad', BAT: '0x0e4fcEC26c9f85c3D714370c98f43C4E02Fc35Ae', @@ -321,6 +341,8 @@ export const CommonsConfig: ICommonConfiguration = { [EthereumNetwork.kovan]: {}, [EthereumNetwork.ropsten]: {}, [EthereumNetwork.tenderlyMain]: {}, + [eEthereumNetwork.matic]: {}, + [eEthereumNetwork.mumbai]: {}, }, ReservesConfig: {}, ATokenDomainSeparator: { @@ -334,6 +356,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '', [eEthereumNetwork.tenderlyMain]: '', + [EthereumNetwork.mumbai]: '', + [EthereumNetwork.matic]: '', }, WETH: { [eEthereumNetwork.coverage]: '', // deployed in local evm @@ -343,6 +367,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0xc778417e063141139fce010982780140aa0cd5ab', [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', [eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + [EthereumNetwork.mumbai]: '', + [EthereumNetwork.matic]: '', }, ReserveFactorTreasuryAddress: { [eEthereumNetwork.coverage]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', @@ -352,5 +378,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.main]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.tenderlyMain]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [EthereumNetwork.mumbai]: '', + [EthereumNetwork.matic]: '', }, }; diff --git a/markets/aave/index.ts b/markets/aave/index.ts index eefcdd3b..0f4d56c8 100644 --- a/markets/aave/index.ts +++ b/markets/aave/index.ts @@ -58,6 +58,8 @@ export const AaveConfig: IAaveConfiguration = { [eEthereumNetwork.buidlerevm]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.coverage]: {}, + [eEthereumNetwork.matic]: {}, + [eEthereumNetwork.mumbai]: {}, [EthereumNetwork.kovan]: { AAVE: '0xB597cd8D3217ea6477232F9217fa70837ff667Af', BAT: '0x2d12186Fbb9f9a8C28B3FfdD4c42920f8539D738', diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index da376b39..b87447d4 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -147,6 +147,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: undefined, [eEthereumNetwork.main]: undefined, [eEthereumNetwork.tenderlyMain]: undefined, + [eEthereumNetwork.mumbai]: undefined, + [eEthereumNetwork.matic]: undefined, }, PoolAdminIndex: 0, EmergencyAdmin: { @@ -157,6 +159,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: undefined, [eEthereumNetwork.main]: undefined, [eEthereumNetwork.tenderlyMain]: undefined, + [eEthereumNetwork.mumbai]: undefined, + [eEthereumNetwork.matic]: undefined, }, EmergencyAdminIndex: 1, ProviderRegistry: { @@ -167,6 +171,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, ProviderRegistryOwner: { // TEMPORARILY USING MY DEPLOYER [eEthereumNetwork.kovan]: '0x18d9bA2baEfBdE0FF137C4ad031427EF205f1Fd9',//'0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', @@ -176,6 +182,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, LendingRateOracle: { [eEthereumNetwork.coverage]: '', @@ -185,6 +193,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', [eEthereumNetwork.main]: '', //'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', // Need to re-deploy because of onlyOwner [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, LendingPoolCollateralManager: { [eEthereumNetwork.coverage]: '', @@ -194,6 +204,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, TokenDistributor: { [eEthereumNetwork.coverage]: '', @@ -203,6 +215,8 @@ export const CommonsConfig: ICommonConfiguration = { [EthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c', [EthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', [EthereumNetwork.tenderlyMain]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, AaveOracle: { [eEthereumNetwork.coverage]: '', @@ -212,6 +226,8 @@ export const CommonsConfig: ICommonConfiguration = { [EthereumNetwork.ropsten]: ZERO_ADDRESS, [EthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', // Need to re-deploy because of onlyOwner [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, FallbackOracle: { [eEthereumNetwork.coverage]: '', @@ -221,6 +237,8 @@ export const CommonsConfig: ICommonConfiguration = { [EthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d', [EthereumNetwork.main]: ZERO_ADDRESS, [EthereumNetwork.tenderlyMain]: ZERO_ADDRESS, + [eEthereumNetwork.mumbai]: ZERO_ADDRESS, + [eEthereumNetwork.matic]: ZERO_ADDRESS, }, ChainlinkAggregator: { [eEthereumNetwork.coverage]: {}, @@ -294,6 +312,8 @@ export const CommonsConfig: ICommonConfiguration = { LpBalWBTCWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, + [eEthereumNetwork.mumbai]: {}, + [eEthereumNetwork.matic]: {}, }, ReserveAssets: { [eEthereumNetwork.coverage]: {}, @@ -303,6 +323,8 @@ export const CommonsConfig: ICommonConfiguration = { [EthereumNetwork.kovan]: {}, [EthereumNetwork.ropsten]: {}, [EthereumNetwork.tenderlyMain]: {}, + [eEthereumNetwork.mumbai]: {}, + [eEthereumNetwork.matic]: {}, }, ReservesConfig: {}, ATokenDomainSeparator: { @@ -316,6 +338,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '', [eEthereumNetwork.tenderlyMain]: '', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, WETH: { [eEthereumNetwork.coverage]: '', // deployed in local evm @@ -325,6 +349,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0xc778417e063141139fce010982780140aa0cd5ab', [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', [eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, ReserveFactorTreasuryAddress: { [eEthereumNetwork.coverage]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', @@ -334,5 +360,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.main]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.tenderlyMain]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', }, }; diff --git a/markets/lp/index.ts b/markets/lp/index.ts index c1105a05..d91b5596 100644 --- a/markets/lp/index.ts +++ b/markets/lp/index.ts @@ -58,6 +58,8 @@ export const lpConfig: ILpConfiguration = { [eEthereumNetwork.buidlerevm]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.coverage]: {}, + [eEthereumNetwork.matic]: {}, + [eEthereumNetwork.mumbai]: {}, [EthereumNetwork.kovan]: { LpDAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', LpUSDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index e69de29b..5a6df636 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -0,0 +1,384 @@ +import BigNumber from 'bignumber.js'; +import { oneEther, oneRay, RAY, ZERO_ADDRESS } from '../../helpers/constants'; +import { ICommonConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; + +const MOCK_CHAINLINK_AGGREGATORS_PRICES = { + AAVE: oneEther.multipliedBy('0.003620948469').toFixed(), + BAT: oneEther.multipliedBy('0.00137893825230').toFixed(), + BUSD: oneEther.multipliedBy('0.00736484').toFixed(), + DAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + ENJ: oneEther.multipliedBy('0.00029560').toFixed(), + KNC: oneEther.multipliedBy('0.001072').toFixed(), + LINK: oneEther.multipliedBy('0.009955').toFixed(), + MANA: oneEther.multipliedBy('0.000158').toFixed(), + MKR: oneEther.multipliedBy('2.508581').toFixed(), + REN: oneEther.multipliedBy('0.00065133').toFixed(), + SNX: oneEther.multipliedBy('0.00442616').toFixed(), + SUSD: oneEther.multipliedBy('0.00364714136416').toFixed(), + TUSD: oneEther.multipliedBy('0.00364714136416').toFixed(), + UNI: oneEther.multipliedBy('0.00536479').toFixed(), + USDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + USDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + WETH: oneEther.toFixed(), + WBTC: oneEther.multipliedBy('47.332685').toFixed(), + YFI: oneEther.multipliedBy('22.407436').toFixed(), + ZRX: oneEther.multipliedBy('0.001151').toFixed(), + LpDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + LpUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), + LpWETH: oneEther.toFixed(), + LpUniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), + LpUniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), + LpUniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), + LpUniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpUniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), + LpUniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), + LpBalWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + USD: '5848466240000000', +}; + +// ---------------- +// PROTOCOL GLOBAL PARAMS +// ---------------- + +export const CommonsConfig: ICommonConfiguration = { + MarketId: 'Commons', + ProviderId: 0, + 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(), + }, + DAI: { + borrowRate: oneRay.multipliedBy(0.039).toFixed(), + }, + TUSD: { + borrowRate: oneRay.multipliedBy(0.035).toFixed(), + }, + USDC: { + borrowRate: oneRay.multipliedBy(0.039).toFixed(), + }, + SUSD: { + borrowRate: oneRay.multipliedBy(0.035).toFixed(), + }, + USDT: { + borrowRate: oneRay.multipliedBy(0.035).toFixed(), + }, + BAT: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + AAVE: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + LINK: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + KNC: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + MKR: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + MANA: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + WBTC: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + ZRX: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + SNX: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + YFI: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + REN: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + UNI: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + BUSD: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + }, + // ---------------- + // COMMON PROTOCOL ADDRESSES ACROSS POOLS + // ---------------- + + // If PoolAdmin/emergencyAdmin is set, will take priority over PoolAdminIndex/emergencyAdminIndex + PoolAdmin: { + [eEthereumNetwork.coverage]: undefined, + [eEthereumNetwork.buidlerevm]: undefined, + [eEthereumNetwork.coverage]: undefined, + [eEthereumNetwork.hardhat]: undefined, + [eEthereumNetwork.kovan]: undefined, + [eEthereumNetwork.ropsten]: undefined, + [eEthereumNetwork.main]: undefined, + [eEthereumNetwork.tenderlyMain]: undefined, + [eEthereumNetwork.mumbai]: undefined, + [eEthereumNetwork.matic]: undefined, + }, + PoolAdminIndex: 0, + EmergencyAdmin: { + [eEthereumNetwork.hardhat]: undefined, + [eEthereumNetwork.coverage]: undefined, + [eEthereumNetwork.buidlerevm]: undefined, + [eEthereumNetwork.kovan]: undefined, + [eEthereumNetwork.ropsten]: undefined, + [eEthereumNetwork.main]: undefined, + [eEthereumNetwork.tenderlyMain]: undefined, + [eEthereumNetwork.mumbai]: undefined, + [eEthereumNetwork.matic]: undefined, + }, + EmergencyAdminIndex: 1, + ProviderRegistry: { + [eEthereumNetwork.kovan]: '0x1E40B561EC587036f9789aF83236f057D1ed2A90', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', + }, + ProviderRegistryOwner: { + [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', + }, + LendingRateOracle: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '',//'0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', + [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', + [eEthereumNetwork.main]: '',//'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', + [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', + }, + LendingPoolCollateralManager: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '0x9269b6453d0d75370c4c85e5a42977a53efdb72a', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', + [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', + }, + TokenDistributor: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.hardhat]: '', + [EthereumNetwork.kovan]: '0x971efe90088f21dc6a36f610ffed77fc19710708', + [EthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c', + [EthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', + [EthereumNetwork.tenderlyMain]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', + }, + AaveOracle: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [EthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', + [EthereumNetwork.ropsten]: ZERO_ADDRESS, + [EthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', + [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', + [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.matic]: '', + }, + FallbackOracle: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [EthereumNetwork.kovan]: '0x50913E8E1c650E790F8a1E741FF9B1B1bB251dfe', + [EthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d', + [EthereumNetwork.main]: ZERO_ADDRESS, + [EthereumNetwork.tenderlyMain]: ZERO_ADDRESS, + [eEthereumNetwork.mumbai]: ZERO_ADDRESS, + [eEthereumNetwork.matic]: ZERO_ADDRESS, + }, + ChainlinkAggregator: { + [eEthereumNetwork.coverage]: {}, + [eEthereumNetwork.hardhat]: {}, + [eEthereumNetwork.buidlerevm]: {}, + [eEthereumNetwork.matic]: {}, + [eEthereumNetwork.mumbai]: {}, + [EthereumNetwork.kovan]: { + AAVE: '0xd04647B7CB523bb9f26730E9B6dE1174db7591Ad', + BAT: '0x0e4fcEC26c9f85c3D714370c98f43C4E02Fc35Ae', + BUSD: '0xbF7A18ea5DE0501f7559144e702b29c55b055CcB', + DAI: '0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', + ENJ: '0xfaDbe2ee798889F02d1d39eDaD98Eff4c7fe95D4', + KNC: '0xb8E8130d244CFd13a75D6B9Aee029B1C33c808A7', + LINK: '0x3Af8C569ab77af5230596Acf0E8c2F9351d24C38', + MANA: '0x1b93D8E109cfeDcBb3Cc74eD761DE286d5771511', + MKR: '0x0B156192e04bAD92B6C1C13cf8739d14D78D5701', + REN: '0xF1939BECE7708382b5fb5e559f630CB8B39a10ee', + SNX: '0xF9A76ae7a1075Fe7d646b06fF05Bd48b9FA5582e', + SUSD: '0xb343e7a1aF578FA35632435243D814e7497622f7', + TUSD: '0x7aeCF1c19661d12E962b69eBC8f6b2E63a55C660', + UNI: '0x17756515f112429471F86f98D5052aCB6C47f6ee', + USDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', + USDT: '0x0bF499444525a23E7Bb61997539725cA2e928138', + WBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', + YFI: '0xC5d1B1DEb2992738C0273408ac43e1e906086B6C', + ZRX: '0xBc3f28Ccc21E9b5856E81E6372aFf57307E2E883', + USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', + }, + [EthereumNetwork.ropsten]: { + AAVE: ZERO_ADDRESS, + BAT: '0xafd8186c962daf599f171b8600f3e19af7b52c92', + BUSD: '0x0A32D96Ff131cd5c3E0E5AAB645BF009Eda61564', + DAI: '0x64b8e49baded7bfb2fd5a9235b2440c0ee02971b', + ENJ: ZERO_ADDRESS, + KNC: '0x19d97ceb36624a31d827032d8216dd2eb15e9845', + LINK: '0xb8c99b98913bE2ca4899CdcaF33a3e519C20EeEc', + MANA: '0xDab909dedB72573c626481fC98CEE1152b81DEC2', + MKR: '0x811B1f727F8F4aE899774B568d2e72916D91F392', + REN: ZERO_ADDRESS, + SNX: '0xA95674a8Ed9aa9D2E445eb0024a9aa05ab44f6bf', + SUSD: '0xe054b4aee7ac7645642dd52f1c892ff0128c98f0', + TUSD: '0x523ac85618df56e940534443125ef16daf785620', + UNI: ZERO_ADDRESS, + USDC: '0xe1480303dde539e2c241bdc527649f37c9cbef7d', + USDT: '0xc08fe0c4d97ccda6b40649c6da621761b628c288', + WBTC: '0x5b8B87A0abA4be247e660B0e0143bB30Cdf566AF', + YFI: ZERO_ADDRESS, + ZRX: '0x1d0052e4ae5b4ae4563cbac50edc3627ca0460d7', + USD: '0x8468b2bDCE073A157E560AA4D9CcF6dB1DB98507', + }, + [EthereumNetwork.main]: { + AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', + BAT: '0x0d16d4528239e9ee52fa531af613AcdB23D88c94', + BUSD: '0x614715d2Af89E6EC99A233818275142cE88d1Cfd', + DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', + ENJ: '0x24D9aB51950F3d62E9144fdC2f3135DAA6Ce8D1B', + KNC: '0x656c0544eF4C98A6a98491833A89204Abb045d6b', + LINK: '0xDC530D9457755926550b59e8ECcdaE7624181557', + MANA: '0x82A44D92D6c329826dc557c5E1Be6ebeC5D5FeB9', + MKR: '0x24551a8Fb2A7211A25a17B1481f043A8a8adC7f2', + REN: '0x3147D7203354Dc06D9fd350c7a2437bcA92387a4', + SNX: '0x79291A9d692Df95334B1a0B3B4AE6bC606782f8c', + SUSD: '0x8e0b7e6062272B5eF4524250bFFF8e5Bd3497757', + TUSD: '0x3886BA987236181D98F2401c507Fb8BeA7871dF2', + UNI: '0xD6aA3D25116d8dA79Ea0246c4826EB951872e02e', + USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', + USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', + WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', + YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4', + ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', + USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + }, + [EthereumNetwork.tenderlyMain]: { + AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', + BAT: '0x0d16d4528239e9ee52fa531af613AcdB23D88c94', + BUSD: '0x614715d2Af89E6EC99A233818275142cE88d1Cfd', + DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', + ENJ: '0x24D9aB51950F3d62E9144fdC2f3135DAA6Ce8D1B', + KNC: '0x656c0544eF4C98A6a98491833A89204Abb045d6b', + LINK: '0xDC530D9457755926550b59e8ECcdaE7624181557', + MANA: '0x82A44D92D6c329826dc557c5E1Be6ebeC5D5FeB9', + MKR: '0x24551a8Fb2A7211A25a17B1481f043A8a8adC7f2', + REN: '0x3147D7203354Dc06D9fd350c7a2437bcA92387a4', + SNX: '0x79291A9d692Df95334B1a0B3B4AE6bC606782f8c', + SUSD: '0x8e0b7e6062272B5eF4524250bFFF8e5Bd3497757', + TUSD: '0x3886BA987236181D98F2401c507Fb8BeA7871dF2', + UNI: '0xD6aA3D25116d8dA79Ea0246c4826EB951872e02e', + USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', + USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', + WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', + YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4', + ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', + USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + }, + }, + ReserveAssets: { + [eEthereumNetwork.coverage]: {}, + [eEthereumNetwork.hardhat]: {}, + [eEthereumNetwork.buidlerevm]: {}, + [EthereumNetwork.main]: {}, + [EthereumNetwork.kovan]: {}, + [EthereumNetwork.ropsten]: {}, + [EthereumNetwork.tenderlyMain]: {}, + [eEthereumNetwork.matic]: {}, + [eEthereumNetwork.mumbai]: {}, + }, + ReservesConfig: {}, + ATokenDomainSeparator: { + [eEthereumNetwork.coverage]: + '0x95b73a72c6ecf4ccbbba5178800023260bad8e75cdccdb8e4827a2977a37c820', + [eEthereumNetwork.hardhat]: + '0xbae024d959c6a022dc5ed37294cd39c141034b2ae5f02a955cce75c930a81bf5', + [eEthereumNetwork.buidlerevm]: + '0xbae024d959c6a022dc5ed37294cd39c141034b2ae5f02a955cce75c930a81bf5', + [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + [EthereumNetwork.mumbai]: '', + [EthereumNetwork.matic]: '', + }, + WETH: { + [eEthereumNetwork.coverage]: '', // deployed in local evm + [eEthereumNetwork.hardhat]: '', // deployed in local evm + [eEthereumNetwork.buidlerevm]: '', // deployed in local evm + [eEthereumNetwork.kovan]: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', + [eEthereumNetwork.ropsten]: '0xc778417e063141139fce010982780140aa0cd5ab', + [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + [eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + [EthereumNetwork.mumbai]: '', + [EthereumNetwork.matic]: '', + }, + ReserveFactorTreasuryAddress: { + [eEthereumNetwork.coverage]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.hardhat]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.buidlerevm]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.kovan]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.ropsten]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.main]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.tenderlyMain]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [EthereumNetwork.mumbai]: '', + [EthereumNetwork.matic]: '', + }, +}; diff --git a/markets/matic/index.ts b/markets/matic/index.ts index 8b137891..0f4d56c8 100644 --- a/markets/matic/index.ts +++ b/markets/matic/index.ts @@ -1 +1,154 @@ +import { oneRay, ZERO_ADDRESS } from '../../helpers/constants'; +import { IAaveConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; +import { CommonsConfig } from './commons'; +import { + strategyBUSD, + strategyDAI, + strategySUSD, + strategyTUSD, + strategyUSDC, + strategyUSDT, + strategyAAVE, + strategyBAT, + strategyZRX, + strategyKNC, + strategyLINK, + strategyMANA, + strategyMKR, + strategyREN, + strategySNX, + strategyUNI, + strategyWBTC, + strategyWETH, + strategyYFI, +} from './reservesConfigs'; + +// ---------------- +// POOL--SPECIFIC PARAMS +// ---------------- + +export const AaveConfig: IAaveConfiguration = { + ...CommonsConfig, + MarketId: 'Aave genesis market', + ProviderId: 1, + ReservesConfig: { + AAVE: strategyAAVE, + BAT: strategyBAT, + BUSD: strategyBUSD, + DAI: strategyDAI, + ENJ: strategyREN, + KNC: strategyKNC, + LINK: strategyLINK, + MANA: strategyMANA, + MKR: strategyMKR, + REN: strategyREN, + SNX: strategySNX, + SUSD: strategySUSD, + TUSD: strategyTUSD, + UNI: strategyUNI, + USDC: strategyUSDC, + USDT: strategyUSDT, + WBTC: strategyWBTC, + WETH: strategyWETH, + YFI: strategyYFI, + ZRX: strategyZRX, + }, + ReserveAssets: { + [eEthereumNetwork.buidlerevm]: {}, + [eEthereumNetwork.hardhat]: {}, + [eEthereumNetwork.coverage]: {}, + [eEthereumNetwork.matic]: {}, + [eEthereumNetwork.mumbai]: {}, + [EthereumNetwork.kovan]: { + AAVE: '0xB597cd8D3217ea6477232F9217fa70837ff667Af', + BAT: '0x2d12186Fbb9f9a8C28B3FfdD4c42920f8539D738', + BUSD: '0x4c6E1EFC12FDfD568186b7BAEc0A43fFfb4bCcCf', + DAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', + ENJ: '0xC64f90Cd7B564D3ab580eb20a102A8238E218be2', + KNC: '0x3F80c39c0b96A0945f9F0E9f55d8A8891c5671A8', + LINK: '0xAD5ce863aE3E4E9394Ab43d4ba0D80f419F61789', + MANA: '0x738Dc6380157429e957d223e6333Dc385c85Fec7', + MKR: '0x61e4CAE3DA7FD189e52a4879C7B8067D7C2Cc0FA', + REN: '0x5eebf65A6746eed38042353Ba84c8e37eD58Ac6f', + SNX: '0x7FDb81B0b8a010dd4FFc57C3fecbf145BA8Bd947', + SUSD: '0x99b267b9D96616f906D53c26dECf3C5672401282', + TUSD: '0x016750AC630F711882812f24Dba6c95b9D35856d', + UNI: '0x075A36BA8846C6B6F53644fDd3bf17E5151789DC', + USDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', + USDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', + WBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', + WETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', + YFI: '0xb7c325266ec274fEb1354021D27FA3E3379D840d', + ZRX: '0xD0d76886cF8D952ca26177EB7CfDf83bad08C00C', + }, + [EthereumNetwork.ropsten]: { + AAVE: '', + BAT: '0x85B24b3517E3aC7bf72a14516160541A60cFF19d', + BUSD: '0xFA6adcFf6A90c11f31Bc9bb59eC0a6efB38381C6', + DAI: '0xf80A32A835F79D7787E8a8ee5721D0fEaFd78108', + ENJ: ZERO_ADDRESS, + KNC: '0xCe4aA1dE3091033Ba74FA2Ad951f6adc5E5cF361', + LINK: '0x1a906E71FF9e28d8E01460639EB8CF0a6f0e2486', + MANA: '0x78b1F763857C8645E46eAdD9540882905ff32Db7', + MKR: '0x2eA9df3bABe04451c9C3B06a2c844587c59d9C37', + REN: ZERO_ADDRESS, + SNX: '0xF80Aa7e2Fda4DA065C55B8061767F729dA1476c7', + SUSD: '0xc374eB17f665914c714Ac4cdC8AF3a3474228cc5', + TUSD: '0xa2EA00Df6d8594DBc76b79beFe22db9043b8896F', + UNI: ZERO_ADDRESS, + USDC: '0x851dEf71f0e6A903375C1e536Bd9ff1684BAD802', + USDT: '0xB404c51BBC10dcBE948077F18a4B8E553D160084', + WBTC: '0xa0E54Ab6AA5f0bf1D62EC3526436F3c05b3348A0', + WETH: '0xc778417e063141139fce010982780140aa0cd5ab', + YFI: ZERO_ADDRESS, + ZRX: '0x02d7055704EfF050323A2E5ee4ba05DB2A588959', + }, + [EthereumNetwork.main]: { + AAVE: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', + BAT: '0x0d8775f648430679a709e98d2b0cb6250d2887ef', + BUSD: '0x4Fabb145d64652a948d72533023f6E7A623C7C53', + DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + ENJ: '0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c', + KNC: '0xdd974D5C2e2928deA5F71b9825b8b646686BD200', + LINK: '0x514910771AF9Ca656af840dff83E8264EcF986CA', + MANA: '0x0F5D2fB29fb7d3CFeE444a200298f468908cC942', + MKR: '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', + REN: '0x408e41876cCCDC0F92210600ef50372656052a38', + SNX: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F', + SUSD: '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51', + TUSD: '0x0000000000085d4780B73119b644AE5ecd22b376', + UNI: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', + USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + YFI: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', + ZRX: '0xE41d2489571d322189246DaFA5ebDe1F4699F498', + }, + [EthereumNetwork.tenderlyMain]: { + AAVE: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', + BAT: '0x0d8775f648430679a709e98d2b0cb6250d2887ef', + BUSD: '0x4Fabb145d64652a948d72533023f6E7A623C7C53', + DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + ENJ: '0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c', + KNC: '0xdd974D5C2e2928deA5F71b9825b8b646686BD200', + LINK: '0x514910771AF9Ca656af840dff83E8264EcF986CA', + MANA: '0x0F5D2fB29fb7d3CFeE444a200298f468908cC942', + MKR: '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', + REN: '0x408e41876cCCDC0F92210600ef50372656052a38', + SNX: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F', + SUSD: '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51', + TUSD: '0x0000000000085d4780B73119b644AE5ecd22b376', + UNI: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', + USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + YFI: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', + ZRX: '0xE41d2489571d322189246DaFA5ebDe1F4699F498', + }, + }, +}; + +export default AaveConfig; diff --git a/markets/matic/rateStrategies.ts b/markets/matic/rateStrategies.ts index e69de29b..afe19b63 100644 --- a/markets/matic/rateStrategies.ts +++ b/markets/matic/rateStrategies.ts @@ -0,0 +1,91 @@ +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(), +} diff --git a/markets/matic/reservesConfigs.ts b/markets/matic/reservesConfigs.ts index e69de29b..6921afed 100644 --- a/markets/matic/reservesConfigs.ts +++ b/markets/matic/reservesConfigs.ts @@ -0,0 +1,254 @@ +// import BigNumber from 'bignumber.js'; +// import { oneRay } from '../../helpers/constants'; +import { eContractid, IReserveParams } from '../../helpers/types'; +import { + rateStrategyStableOne, + rateStrategyStableTwo, + rateStrategyStableThree, + rateStrategyWETH, + rateStrategyAAVE, + rateStrategyVolatileOne, + rateStrategyVolatileTwo, + rateStrategyVolatileThree, +} 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' +}; \ No newline at end of file From 093007c24771fecef976352cd43e22fa1c2e58f1 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 16:45:33 -0500 Subject: [PATCH 113/219] Fix Matic commons to bring up to speed --- markets/matic/commons.ts | 45 +++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index 5a6df636..773eb610 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -23,35 +23,38 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), - LpDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - LpUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), - LpWETH: oneEther.toFixed(), - LpUniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), - LpUniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), - LpUniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), - LpUniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpUniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), - LpUniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), - LpBalWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + // LpDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + // LpUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + // LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + // LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), + // LpWETH: oneEther.toFixed(), + UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), + UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), + UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), + UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), + UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), + BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), USD: '5848466240000000', }; - // ---------------- // PROTOCOL GLOBAL PARAMS // ---------------- export const CommonsConfig: ICommonConfiguration = { MarketId: 'Commons', + ATokenNamePrefix: 'Aave interest bearing', + StableDebtTokenNamePrefix: 'Aave stable debt bearing', + VariableDebtTokenNamePrefix: 'Aave variable debt bearing', + SymbolPrefix: '', ProviderId: 0, ProtocolGlobalParams: { TokenDistributorPercentageBase: '10000', From ca1df823eaf73cceb51fbda8e5081d647234e681 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 17:38:44 -0500 Subject: [PATCH 114/219] Including MATIC token in comons --- markets/aave/commons.ts | 3 ++- markets/lp/commons.ts | 3 ++- markets/matic/commons.ts | 54 ++++++---------------------------------- 3 files changed, 12 insertions(+), 48 deletions(-) diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index 773eb610..853c252e 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -43,6 +43,7 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + MATIC: oneEther.multipliedBy('0.003620948469').toFixed(), USD: '5848466240000000', }; // ---------------- @@ -55,7 +56,7 @@ export const CommonsConfig: ICommonConfiguration = { StableDebtTokenNamePrefix: 'Aave stable debt bearing', VariableDebtTokenNamePrefix: 'Aave variable debt bearing', SymbolPrefix: '', - ProviderId: 0, + ProviderId: 0, // Overriden in index.ts ProtocolGlobalParams: { TokenDistributorPercentageBase: '10000', MockUsdPriceInWei: '5848466240000000', diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index 867fd029..6e1fb16b 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -43,6 +43,7 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + MATIC: oneEther.multipliedBy('0.003620948469').toFixed(), USD: '5848466240000000', }; // ---------------- @@ -55,7 +56,7 @@ export const CommonsConfig: ICommonConfiguration = { StableDebtTokenNamePrefix: 'Aave AMM Market stable debt', VariableDebtTokenNamePrefix: 'Aave AMM Market variable debt', SymbolPrefix: 'Amm', - ProviderId: 0, + ProviderId: 0, // Overriden in index.ts ProtocolGlobalParams: { TokenDistributorPercentageBase: '10000', MockUsdPriceInWei: '5848466240000000', diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index 773eb610..0c1bccbe 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -43,6 +43,7 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + MATIC: oneEther.multipliedBy('0.003620948469').toFixed(), USD: '5848466240000000', }; // ---------------- @@ -51,11 +52,11 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { export const CommonsConfig: ICommonConfiguration = { MarketId: 'Commons', - ATokenNamePrefix: 'Aave interest bearing', - StableDebtTokenNamePrefix: 'Aave stable debt bearing', - VariableDebtTokenNamePrefix: 'Aave variable debt bearing', - SymbolPrefix: '', - ProviderId: 0, + ATokenNamePrefix: 'Aave Matic Market', + StableDebtTokenNamePrefix: 'Aave Matic Market stable debt', + VariableDebtTokenNamePrefix: 'Aave Matic Market variable debt', + SymbolPrefix: 'Matic', + ProviderId: 0, // Overriden in index.ts ProtocolGlobalParams: { TokenDistributorPercentageBase: '10000', MockUsdPriceInWei: '5848466240000000', @@ -82,56 +83,17 @@ export const CommonsConfig: ICommonConfiguration = { DAI: { borrowRate: oneRay.multipliedBy(0.039).toFixed(), }, - TUSD: { - borrowRate: oneRay.multipliedBy(0.035).toFixed(), - }, USDC: { borrowRate: oneRay.multipliedBy(0.039).toFixed(), }, - SUSD: { - borrowRate: oneRay.multipliedBy(0.035).toFixed(), - }, USDT: { borrowRate: oneRay.multipliedBy(0.035).toFixed(), }, - BAT: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - AAVE: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - LINK: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - KNC: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - MKR: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - MANA: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, WBTC: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - ZRX: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - SNX: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - YFI: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - REN: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - UNI: { - borrowRate: oneRay.multipliedBy(0.03).toFixed(), - }, - BUSD: { - borrowRate: oneRay.multipliedBy(0.05).toFixed(), + MATIC: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), // TEMP }, }, // ---------------- From 016cdacc5f17e4867cabaa29a31331837913a26a Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 17:38:54 -0500 Subject: [PATCH 115/219] Added MATIC token to types --- helpers/types.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/helpers/types.ts b/helpers/types.ts index 8781eadc..4c81d660 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -227,6 +227,7 @@ export interface iAssetBase { UniWBTCUSDC: T; UniYFIWETH: T; BptWBTCWETH: T; + MATIC: T; } export type iAssetsWithoutETH = Omit, 'ETH'>; @@ -281,6 +282,16 @@ export type iLpPoolAssets = Pick< | 'BptWBTCWETH' >; +export type iMaticPoolAssets = Pick< + iAssetsWithoutUSD, + | 'DAI' + | 'USDC' + | 'USDT' + | 'WBTC' + | 'WETH' + | 'MATIC' +>; + export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; export type iAavePoolTokens = Omit, 'ETH'>; @@ -468,6 +479,11 @@ export interface IAaveConfiguration extends ICommonConfiguration { export interface ILpConfiguration extends ICommonConfiguration { ReservesConfig: iLpPoolAssets; } + +export interface IMaticConfiguration extends ICommonConfiguration { + ReservesConfig: iMaticPoolAssets; +} + export interface ITokenAddress { [token: string]: tEthereumAddress; } From 8eca8a0796216a1f0a1f62cfd04aaf8dc279ba56 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 17:39:16 -0500 Subject: [PATCH 116/219] Cleanup Matic config --- markets/matic/index.ts | 188 +++++++++++++----------------- markets/matic/reservesConfigs.ts | 193 ++----------------------------- 2 files changed, 90 insertions(+), 291 deletions(-) diff --git a/markets/matic/index.ts b/markets/matic/index.ts index 0f4d56c8..bbe4e922 100644 --- a/markets/matic/index.ts +++ b/markets/matic/index.ts @@ -1,152 +1,120 @@ import { oneRay, ZERO_ADDRESS } from '../../helpers/constants'; -import { IAaveConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; +import { IMaticConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; import { CommonsConfig } from './commons'; import { - strategyBUSD, strategyDAI, - strategySUSD, - strategyTUSD, strategyUSDC, strategyUSDT, - strategyAAVE, - strategyBAT, - strategyZRX, - strategyKNC, - strategyLINK, - strategyMANA, - strategyMKR, - strategyREN, - strategySNX, - strategyUNI, strategyWBTC, strategyWETH, - strategyYFI, + strategyMATIC, } from './reservesConfigs'; // ---------------- // POOL--SPECIFIC PARAMS // ---------------- -export const AaveConfig: IAaveConfiguration = { +export const AaveConfig: IMaticConfiguration = { ...CommonsConfig, - MarketId: 'Aave genesis market', - ProviderId: 1, + MarketId: 'Matic Market', + ProviderId: 3, // Unknown? ReservesConfig: { - AAVE: strategyAAVE, - BAT: strategyBAT, - BUSD: strategyBUSD, DAI: strategyDAI, - ENJ: strategyREN, - KNC: strategyKNC, - LINK: strategyLINK, - MANA: strategyMANA, - MKR: strategyMKR, - REN: strategyREN, - SNX: strategySNX, - SUSD: strategySUSD, - TUSD: strategyTUSD, - UNI: strategyUNI, USDC: strategyUSDC, USDT: strategyUSDT, WBTC: strategyWBTC, WETH: strategyWETH, - YFI: strategyYFI, - ZRX: strategyZRX, + MATIC: strategyMATIC, }, ReserveAssets: { [eEthereumNetwork.buidlerevm]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.coverage]: {}, - [eEthereumNetwork.matic]: {}, - [eEthereumNetwork.mumbai]: {}, + [eEthereumNetwork.matic]: { + DAI: '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063', + USDC: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', + USDT: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F', + WBTC: '0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6', + WETH: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', + MATIC: '0x0000000000000000000000000000000000001010', + }, + [eEthereumNetwork.mumbai]: { + + }, [EthereumNetwork.kovan]: { - AAVE: '0xB597cd8D3217ea6477232F9217fa70837ff667Af', - BAT: '0x2d12186Fbb9f9a8C28B3FfdD4c42920f8539D738', - BUSD: '0x4c6E1EFC12FDfD568186b7BAEc0A43fFfb4bCcCf', - DAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', - ENJ: '0xC64f90Cd7B564D3ab580eb20a102A8238E218be2', - KNC: '0x3F80c39c0b96A0945f9F0E9f55d8A8891c5671A8', - LINK: '0xAD5ce863aE3E4E9394Ab43d4ba0D80f419F61789', - MANA: '0x738Dc6380157429e957d223e6333Dc385c85Fec7', - MKR: '0x61e4CAE3DA7FD189e52a4879C7B8067D7C2Cc0FA', - REN: '0x5eebf65A6746eed38042353Ba84c8e37eD58Ac6f', - SNX: '0x7FDb81B0b8a010dd4FFc57C3fecbf145BA8Bd947', - SUSD: '0x99b267b9D96616f906D53c26dECf3C5672401282', - TUSD: '0x016750AC630F711882812f24Dba6c95b9D35856d', - UNI: '0x075A36BA8846C6B6F53644fDd3bf17E5151789DC', - USDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', - USDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', - WBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', - WETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', - YFI: '0xb7c325266ec274fEb1354021D27FA3E3379D840d', - ZRX: '0xD0d76886cF8D952ca26177EB7CfDf83bad08C00C', + // AAVE: '0xB597cd8D3217ea6477232F9217fa70837ff667Af', + // BAT: '0x2d12186Fbb9f9a8C28B3FfdD4c42920f8539D738', + // BUSD: '0x4c6E1EFC12FDfD568186b7BAEc0A43fFfb4bCcCf', + // DAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', + // ENJ: '0xC64f90Cd7B564D3ab580eb20a102A8238E218be2', + // KNC: '0x3F80c39c0b96A0945f9F0E9f55d8A8891c5671A8', + // LINK: '0xAD5ce863aE3E4E9394Ab43d4ba0D80f419F61789', + // MANA: '0x738Dc6380157429e957d223e6333Dc385c85Fec7', + // MKR: '0x61e4CAE3DA7FD189e52a4879C7B8067D7C2Cc0FA', + // REN: '0x5eebf65A6746eed38042353Ba84c8e37eD58Ac6f', + // SNX: '0x7FDb81B0b8a010dd4FFc57C3fecbf145BA8Bd947', + // SUSD: '0x99b267b9D96616f906D53c26dECf3C5672401282', + // TUSD: '0x016750AC630F711882812f24Dba6c95b9D35856d', + // UNI: '0x075A36BA8846C6B6F53644fDd3bf17E5151789DC', + // USDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', + // USDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', + // WBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', + // WETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', + // YFI: '0xb7c325266ec274fEb1354021D27FA3E3379D840d', + // ZRX: '0xD0d76886cF8D952ca26177EB7CfDf83bad08C00C', }, [EthereumNetwork.ropsten]: { - AAVE: '', - BAT: '0x85B24b3517E3aC7bf72a14516160541A60cFF19d', - BUSD: '0xFA6adcFf6A90c11f31Bc9bb59eC0a6efB38381C6', - DAI: '0xf80A32A835F79D7787E8a8ee5721D0fEaFd78108', - ENJ: ZERO_ADDRESS, - KNC: '0xCe4aA1dE3091033Ba74FA2Ad951f6adc5E5cF361', - LINK: '0x1a906E71FF9e28d8E01460639EB8CF0a6f0e2486', - MANA: '0x78b1F763857C8645E46eAdD9540882905ff32Db7', - MKR: '0x2eA9df3bABe04451c9C3B06a2c844587c59d9C37', - REN: ZERO_ADDRESS, - SNX: '0xF80Aa7e2Fda4DA065C55B8061767F729dA1476c7', - SUSD: '0xc374eB17f665914c714Ac4cdC8AF3a3474228cc5', - TUSD: '0xa2EA00Df6d8594DBc76b79beFe22db9043b8896F', - UNI: ZERO_ADDRESS, - USDC: '0x851dEf71f0e6A903375C1e536Bd9ff1684BAD802', - USDT: '0xB404c51BBC10dcBE948077F18a4B8E553D160084', - WBTC: '0xa0E54Ab6AA5f0bf1D62EC3526436F3c05b3348A0', - WETH: '0xc778417e063141139fce010982780140aa0cd5ab', - YFI: ZERO_ADDRESS, - ZRX: '0x02d7055704EfF050323A2E5ee4ba05DB2A588959', + // AAVE: '', + // BAT: '0x85B24b3517E3aC7bf72a14516160541A60cFF19d', + // BUSD: '0xFA6adcFf6A90c11f31Bc9bb59eC0a6efB38381C6', + // DAI: '0xf80A32A835F79D7787E8a8ee5721D0fEaFd78108', + // ENJ: ZERO_ADDRESS, + // KNC: '0xCe4aA1dE3091033Ba74FA2Ad951f6adc5E5cF361', + // LINK: '0x1a906E71FF9e28d8E01460639EB8CF0a6f0e2486', + // MANA: '0x78b1F763857C8645E46eAdD9540882905ff32Db7', + // MKR: '0x2eA9df3bABe04451c9C3B06a2c844587c59d9C37', + // REN: ZERO_ADDRESS, + // SNX: '0xF80Aa7e2Fda4DA065C55B8061767F729dA1476c7', + // SUSD: '0xc374eB17f665914c714Ac4cdC8AF3a3474228cc5', + // TUSD: '0xa2EA00Df6d8594DBc76b79beFe22db9043b8896F', + // UNI: ZERO_ADDRESS, + // USDC: '0x851dEf71f0e6A903375C1e536Bd9ff1684BAD802', + // USDT: '0xB404c51BBC10dcBE948077F18a4B8E553D160084', + // WBTC: '0xa0E54Ab6AA5f0bf1D62EC3526436F3c05b3348A0', + // WETH: '0xc778417e063141139fce010982780140aa0cd5ab', + // YFI: ZERO_ADDRESS, + // ZRX: '0x02d7055704EfF050323A2E5ee4ba05DB2A588959', }, [EthereumNetwork.main]: { - AAVE: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', - BAT: '0x0d8775f648430679a709e98d2b0cb6250d2887ef', - BUSD: '0x4Fabb145d64652a948d72533023f6E7A623C7C53', DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - ENJ: '0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c', - KNC: '0xdd974D5C2e2928deA5F71b9825b8b646686BD200', - LINK: '0x514910771AF9Ca656af840dff83E8264EcF986CA', - MANA: '0x0F5D2fB29fb7d3CFeE444a200298f468908cC942', - MKR: '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', - REN: '0x408e41876cCCDC0F92210600ef50372656052a38', - SNX: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F', - SUSD: '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51', - TUSD: '0x0000000000085d4780B73119b644AE5ecd22b376', - UNI: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - YFI: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', - ZRX: '0xE41d2489571d322189246DaFA5ebDe1F4699F498', + MATIC: '0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', }, [EthereumNetwork.tenderlyMain]: { - AAVE: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', - BAT: '0x0d8775f648430679a709e98d2b0cb6250d2887ef', - BUSD: '0x4Fabb145d64652a948d72533023f6E7A623C7C53', - DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - ENJ: '0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c', - KNC: '0xdd974D5C2e2928deA5F71b9825b8b646686BD200', - LINK: '0x514910771AF9Ca656af840dff83E8264EcF986CA', - MANA: '0x0F5D2fB29fb7d3CFeE444a200298f468908cC942', - MKR: '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', - REN: '0x408e41876cCCDC0F92210600ef50372656052a38', - SNX: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F', - SUSD: '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51', - TUSD: '0x0000000000085d4780B73119b644AE5ecd22b376', - UNI: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', - USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', - WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', - WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - YFI: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', - ZRX: '0xE41d2489571d322189246DaFA5ebDe1F4699F498', + // AAVE: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', + // BAT: '0x0d8775f648430679a709e98d2b0cb6250d2887ef', + // BUSD: '0x4Fabb145d64652a948d72533023f6E7A623C7C53', + // DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + // ENJ: '0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c', + // KNC: '0xdd974D5C2e2928deA5F71b9825b8b646686BD200', + // LINK: '0x514910771AF9Ca656af840dff83E8264EcF986CA', + // MANA: '0x0F5D2fB29fb7d3CFeE444a200298f468908cC942', + // MKR: '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', + // REN: '0x408e41876cCCDC0F92210600ef50372656052a38', + // SNX: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F', + // SUSD: '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51', + // TUSD: '0x0000000000085d4780B73119b644AE5ecd22b376', + // UNI: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', + // USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + // USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + // WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + // WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + // YFI: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', + // ZRX: '0xE41d2489571d322189246DaFA5ebDe1F4699F498', }, }, }; diff --git a/markets/matic/reservesConfigs.ts b/markets/matic/reservesConfigs.ts index 6921afed..608d028b 100644 --- a/markets/matic/reservesConfigs.ts +++ b/markets/matic/reservesConfigs.ts @@ -12,18 +12,6 @@ import { rateStrategyVolatileThree, } 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', @@ -36,30 +24,6 @@ export const strategyDAI: IReserveParams = { 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', @@ -73,51 +37,15 @@ export const strategyUSDC: IReserveParams = { }; 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' + strategy: rateStrategyStableThree, + baseLTVAsCollateral: '8000', + liquidationThreshold: '8500', + liquidationBonus: '10500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '6', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000' }; export const strategyWETH: IReserveParams = { @@ -132,91 +60,6 @@ export const strategyWETH: IReserveParams = { 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', @@ -229,21 +72,9 @@ export const strategyWBTC: IReserveParams = { 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', +export const strategyMATIC: IReserveParams = { + strategy: rateStrategyVolatileOne, //Temp? + baseLTVAsCollateral: '5000', liquidationThreshold: '6500', liquidationBonus: '11000', borrowingEnabled: true, From 7aac51d7d418413c5841b6bc5194ec06376913ba Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 17:43:31 -0500 Subject: [PATCH 117/219] Marked TODO --- markets/matic/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/markets/matic/index.ts b/markets/matic/index.ts index bbe4e922..1cb8ab4d 100644 --- a/markets/matic/index.ts +++ b/markets/matic/index.ts @@ -39,8 +39,8 @@ export const AaveConfig: IMaticConfiguration = { WETH: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', MATIC: '0x0000000000000000000000000000000000001010', }, - [eEthereumNetwork.mumbai]: { - + [eEthereumNetwork.mumbai]: { + // TODO: Deploy mock tokens for testing }, [EthereumNetwork.kovan]: { // AAVE: '0xB597cd8D3217ea6477232F9217fa70837ff667Af', From 33c0ad326cd443edc5d83b83a7f198cac752879d Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 17:52:03 -0500 Subject: [PATCH 118/219] Removed unused assets from config --- markets/matic/commons.ts | 88 ++++------------------------------------ markets/matic/index.ts | 72 ++++---------------------------- 2 files changed, 16 insertions(+), 144 deletions(-) diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index 0c1bccbe..fb89e43a 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -209,93 +209,21 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.buidlerevm]: {}, [eEthereumNetwork.matic]: {}, [eEthereumNetwork.mumbai]: {}, - [EthereumNetwork.kovan]: { - AAVE: '0xd04647B7CB523bb9f26730E9B6dE1174db7591Ad', - BAT: '0x0e4fcEC26c9f85c3D714370c98f43C4E02Fc35Ae', - BUSD: '0xbF7A18ea5DE0501f7559144e702b29c55b055CcB', - DAI: '0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', - ENJ: '0xfaDbe2ee798889F02d1d39eDaD98Eff4c7fe95D4', - KNC: '0xb8E8130d244CFd13a75D6B9Aee029B1C33c808A7', - LINK: '0x3Af8C569ab77af5230596Acf0E8c2F9351d24C38', - MANA: '0x1b93D8E109cfeDcBb3Cc74eD761DE286d5771511', - MKR: '0x0B156192e04bAD92B6C1C13cf8739d14D78D5701', - REN: '0xF1939BECE7708382b5fb5e559f630CB8B39a10ee', - SNX: '0xF9A76ae7a1075Fe7d646b06fF05Bd48b9FA5582e', - SUSD: '0xb343e7a1aF578FA35632435243D814e7497622f7', - TUSD: '0x7aeCF1c19661d12E962b69eBC8f6b2E63a55C660', - UNI: '0x17756515f112429471F86f98D5052aCB6C47f6ee', - USDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', - USDT: '0x0bF499444525a23E7Bb61997539725cA2e928138', - WBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', - YFI: '0xC5d1B1DEb2992738C0273408ac43e1e906086B6C', - ZRX: '0xBc3f28Ccc21E9b5856E81E6372aFf57307E2E883', - USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', - }, - [EthereumNetwork.ropsten]: { - AAVE: ZERO_ADDRESS, - BAT: '0xafd8186c962daf599f171b8600f3e19af7b52c92', - BUSD: '0x0A32D96Ff131cd5c3E0E5AAB645BF009Eda61564', - DAI: '0x64b8e49baded7bfb2fd5a9235b2440c0ee02971b', - ENJ: ZERO_ADDRESS, - KNC: '0x19d97ceb36624a31d827032d8216dd2eb15e9845', - LINK: '0xb8c99b98913bE2ca4899CdcaF33a3e519C20EeEc', - MANA: '0xDab909dedB72573c626481fC98CEE1152b81DEC2', - MKR: '0x811B1f727F8F4aE899774B568d2e72916D91F392', - REN: ZERO_ADDRESS, - SNX: '0xA95674a8Ed9aa9D2E445eb0024a9aa05ab44f6bf', - SUSD: '0xe054b4aee7ac7645642dd52f1c892ff0128c98f0', - TUSD: '0x523ac85618df56e940534443125ef16daf785620', - UNI: ZERO_ADDRESS, - USDC: '0xe1480303dde539e2c241bdc527649f37c9cbef7d', - USDT: '0xc08fe0c4d97ccda6b40649c6da621761b628c288', - WBTC: '0x5b8B87A0abA4be247e660B0e0143bB30Cdf566AF', - YFI: ZERO_ADDRESS, - ZRX: '0x1d0052e4ae5b4ae4563cbac50edc3627ca0460d7', - USD: '0x8468b2bDCE073A157E560AA4D9CcF6dB1DB98507', - }, + [EthereumNetwork.kovan]: {}, + [EthereumNetwork.ropsten]: {}, [EthereumNetwork.main]: { - AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', - BAT: '0x0d16d4528239e9ee52fa531af613AcdB23D88c94', - BUSD: '0x614715d2Af89E6EC99A233818275142cE88d1Cfd', DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', - ENJ: '0x24D9aB51950F3d62E9144fdC2f3135DAA6Ce8D1B', - KNC: '0x656c0544eF4C98A6a98491833A89204Abb045d6b', - LINK: '0xDC530D9457755926550b59e8ECcdaE7624181557', - MANA: '0x82A44D92D6c329826dc557c5E1Be6ebeC5D5FeB9', - MKR: '0x24551a8Fb2A7211A25a17B1481f043A8a8adC7f2', - REN: '0x3147D7203354Dc06D9fd350c7a2437bcA92387a4', - SNX: '0x79291A9d692Df95334B1a0B3B4AE6bC606782f8c', - SUSD: '0x8e0b7e6062272B5eF4524250bFFF8e5Bd3497757', - TUSD: '0x3886BA987236181D98F2401c507Fb8BeA7871dF2', - UNI: '0xD6aA3D25116d8dA79Ea0246c4826EB951872e02e', USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', - YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4', - ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', - USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + MATIC: ZERO_ADDRESS, }, [EthereumNetwork.tenderlyMain]: { - AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', - BAT: '0x0d16d4528239e9ee52fa531af613AcdB23D88c94', - BUSD: '0x614715d2Af89E6EC99A233818275142cE88d1Cfd', DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', - ENJ: '0x24D9aB51950F3d62E9144fdC2f3135DAA6Ce8D1B', - KNC: '0x656c0544eF4C98A6a98491833A89204Abb045d6b', - LINK: '0xDC530D9457755926550b59e8ECcdaE7624181557', - MANA: '0x82A44D92D6c329826dc557c5E1Be6ebeC5D5FeB9', - MKR: '0x24551a8Fb2A7211A25a17B1481f043A8a8adC7f2', - REN: '0x3147D7203354Dc06D9fd350c7a2437bcA92387a4', - SNX: '0x79291A9d692Df95334B1a0B3B4AE6bC606782f8c', - SUSD: '0x8e0b7e6062272B5eF4524250bFFF8e5Bd3497757', - TUSD: '0x3886BA987236181D98F2401c507Fb8BeA7871dF2', - UNI: '0xD6aA3D25116d8dA79Ea0246c4826EB951872e02e', USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', - YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4', - ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', - USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + MATIC: ZERO_ADDRESS, }, }, ReserveAssets: { @@ -332,8 +260,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0xc778417e063141139fce010982780140aa0cd5ab', [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', [eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - [EthereumNetwork.mumbai]: '', - [EthereumNetwork.matic]: '', + [EthereumNetwork.mumbai]: '', // No WETH gateway on L2 + [EthereumNetwork.matic]: '', // No WETH gateway on L2 }, ReserveFactorTreasuryAddress: { [eEthereumNetwork.coverage]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', @@ -343,7 +271,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.main]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.tenderlyMain]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', - [EthereumNetwork.mumbai]: '', - [EthereumNetwork.matic]: '', + [EthereumNetwork.mumbai]: ZERO_ADDRESS, // TEMP + [EthereumNetwork.matic]: ZERO_ADDRESS, // TEMP }, }; diff --git a/markets/matic/index.ts b/markets/matic/index.ts index 1cb8ab4d..f9cfe663 100644 --- a/markets/matic/index.ts +++ b/markets/matic/index.ts @@ -42,50 +42,8 @@ export const AaveConfig: IMaticConfiguration = { [eEthereumNetwork.mumbai]: { // TODO: Deploy mock tokens for testing }, - [EthereumNetwork.kovan]: { - // AAVE: '0xB597cd8D3217ea6477232F9217fa70837ff667Af', - // BAT: '0x2d12186Fbb9f9a8C28B3FfdD4c42920f8539D738', - // BUSD: '0x4c6E1EFC12FDfD568186b7BAEc0A43fFfb4bCcCf', - // DAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', - // ENJ: '0xC64f90Cd7B564D3ab580eb20a102A8238E218be2', - // KNC: '0x3F80c39c0b96A0945f9F0E9f55d8A8891c5671A8', - // LINK: '0xAD5ce863aE3E4E9394Ab43d4ba0D80f419F61789', - // MANA: '0x738Dc6380157429e957d223e6333Dc385c85Fec7', - // MKR: '0x61e4CAE3DA7FD189e52a4879C7B8067D7C2Cc0FA', - // REN: '0x5eebf65A6746eed38042353Ba84c8e37eD58Ac6f', - // SNX: '0x7FDb81B0b8a010dd4FFc57C3fecbf145BA8Bd947', - // SUSD: '0x99b267b9D96616f906D53c26dECf3C5672401282', - // TUSD: '0x016750AC630F711882812f24Dba6c95b9D35856d', - // UNI: '0x075A36BA8846C6B6F53644fDd3bf17E5151789DC', - // USDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', - // USDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', - // WBTC: '0xD1B98B6607330172f1D991521145A22BCe793277', - // WETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', - // YFI: '0xb7c325266ec274fEb1354021D27FA3E3379D840d', - // ZRX: '0xD0d76886cF8D952ca26177EB7CfDf83bad08C00C', - }, - [EthereumNetwork.ropsten]: { - // AAVE: '', - // BAT: '0x85B24b3517E3aC7bf72a14516160541A60cFF19d', - // BUSD: '0xFA6adcFf6A90c11f31Bc9bb59eC0a6efB38381C6', - // DAI: '0xf80A32A835F79D7787E8a8ee5721D0fEaFd78108', - // ENJ: ZERO_ADDRESS, - // KNC: '0xCe4aA1dE3091033Ba74FA2Ad951f6adc5E5cF361', - // LINK: '0x1a906E71FF9e28d8E01460639EB8CF0a6f0e2486', - // MANA: '0x78b1F763857C8645E46eAdD9540882905ff32Db7', - // MKR: '0x2eA9df3bABe04451c9C3B06a2c844587c59d9C37', - // REN: ZERO_ADDRESS, - // SNX: '0xF80Aa7e2Fda4DA065C55B8061767F729dA1476c7', - // SUSD: '0xc374eB17f665914c714Ac4cdC8AF3a3474228cc5', - // TUSD: '0xa2EA00Df6d8594DBc76b79beFe22db9043b8896F', - // UNI: ZERO_ADDRESS, - // USDC: '0x851dEf71f0e6A903375C1e536Bd9ff1684BAD802', - // USDT: '0xB404c51BBC10dcBE948077F18a4B8E553D160084', - // WBTC: '0xa0E54Ab6AA5f0bf1D62EC3526436F3c05b3348A0', - // WETH: '0xc778417e063141139fce010982780140aa0cd5ab', - // YFI: ZERO_ADDRESS, - // ZRX: '0x02d7055704EfF050323A2E5ee4ba05DB2A588959', - }, + [EthereumNetwork.kovan]: {}, + [EthereumNetwork.ropsten]: {}, [EthereumNetwork.main]: { DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', @@ -95,26 +53,12 @@ export const AaveConfig: IMaticConfiguration = { MATIC: '0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', }, [EthereumNetwork.tenderlyMain]: { - // AAVE: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', - // BAT: '0x0d8775f648430679a709e98d2b0cb6250d2887ef', - // BUSD: '0x4Fabb145d64652a948d72533023f6E7A623C7C53', - // DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - // ENJ: '0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c', - // KNC: '0xdd974D5C2e2928deA5F71b9825b8b646686BD200', - // LINK: '0x514910771AF9Ca656af840dff83E8264EcF986CA', - // MANA: '0x0F5D2fB29fb7d3CFeE444a200298f468908cC942', - // MKR: '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', - // REN: '0x408e41876cCCDC0F92210600ef50372656052a38', - // SNX: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F', - // SUSD: '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51', - // TUSD: '0x0000000000085d4780B73119b644AE5ecd22b376', - // UNI: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', - // USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - // USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', - // WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', - // WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - // YFI: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', - // ZRX: '0xE41d2489571d322189246DaFA5ebDe1F4699F498', + DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + MATIC: '0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', }, }, }; From 55df821c96ac02253b8c4864296d2a2ba16e9ecb Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 18:25:26 -0500 Subject: [PATCH 119/219] Added Mumbai mock tokens --- markets/matic/index.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/markets/matic/index.ts b/markets/matic/index.ts index f9cfe663..f48b21d9 100644 --- a/markets/matic/index.ts +++ b/markets/matic/index.ts @@ -39,8 +39,13 @@ export const AaveConfig: IMaticConfiguration = { WETH: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', MATIC: '0x0000000000000000000000000000000000001010', }, - [eEthereumNetwork.mumbai]: { - // TODO: Deploy mock tokens for testing + [eEthereumNetwork.mumbai]: { // Mock tokens with a simple "mint" external function + DAI: '0x13b3fda609C1eeb23b4F4b69257840760dCa6C4a', + USDC: '0x52b63223994433FdE2F1350Ba69Dfd2779f06ABA', + USDT: '0xB3abd1912F586fDFFa13606882c28E27913853d2', + WBTC: '0x393E3512d45a956A628124665672312ea86930Ba', + WETH: '0x53CDb16B8C031B779e996406546614E5F05BC4Bf', + MATIC: '0x0000000000000000000000000000000000001010 ', }, [EthereumNetwork.kovan]: {}, [EthereumNetwork.ropsten]: {}, From 35558625a153b5f1808aa0f26dfbfb393127347a Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 18:30:09 -0500 Subject: [PATCH 120/219] (Same functionality) Brought migration script up to speed. --- tasks/migrations/lp.mainnet.ts | 37 +++++++++++++--------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/tasks/migrations/lp.mainnet.ts b/tasks/migrations/lp.mainnet.ts index 70121c03..912f48b4 100644 --- a/tasks/migrations/lp.mainnet.ts +++ b/tasks/migrations/lp.mainnet.ts @@ -1,15 +1,13 @@ -import {task} from 'hardhat/config'; -import {ExternalProvider} from '@ethersproject/providers'; -import {checkVerification} from '../../helpers/etherscan-verification'; -import {ConfigNames} from '../../helpers/configuration'; -import {EthereumNetworkNames} from '../../helpers/types'; -import {printContracts} from '../../helpers/misc-utils'; +import { task } from 'hardhat/config'; +import { checkVerification } from '../../helpers/etherscan-verification'; +import { ConfigNames } from '../../helpers/configuration'; +import { printContracts } from '../../helpers/misc-utils'; +import { usingTenderly } from '../../helpers/tenderly-utils'; task('lp:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({verify}, DRE) => { + .setAction(async ({ verify }, DRE) => { const POOL_NAME = ConfigNames.Lp; - const network = DRE.network.name; await DRE.run('set-DRE'); // Prevent loss of gas verifying all the needed ENVs for Etherscan verification @@ -17,40 +15,33 @@ task('lp:mainnet', 'Deploy development enviroment') checkVerification(); } - if (network.includes('tenderly')) { - console.log('- Setting up Tenderly provider'); - await DRE.tenderlyRPC.initializeFork(); - const provider = new DRE.ethers.providers.Web3Provider(DRE.tenderlyRPC as any); - DRE.ethers.provider = provider; - } - console.log('Migration started\n'); console.log('1. Deploy address provider'); - await DRE.run('full:deploy-address-provider', {pool: POOL_NAME}); - + await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); + console.log('2. Deploy lending pool'); await DRE.run('full:deploy-lending-pool'); console.log('3. Deploy oracles'); - await DRE.run('full:deploy-oracles', {pool: POOL_NAME}); + await DRE.run('full:deploy-oracles', { pool: POOL_NAME }); console.log('4. Deploy Data Provider'); - await DRE.run('full:data-provider', {pool: POOL_NAME}); + await DRE.run('full:data-provider', { pool: POOL_NAME }); console.log('5. Initialize lending pool'); - await DRE.run('full:initialize-lending-pool', {pool: POOL_NAME}); + await DRE.run('full:initialize-lending-pool', { pool: POOL_NAME }); if (verify) { printContracts(); console.log('4. Veryfing contracts'); - await DRE.run('verify:general', {all: true, pool: POOL_NAME}); + await DRE.run('verify:general', { all: true, pool: POOL_NAME }); console.log('5. Veryfing aTokens and debtTokens'); - await DRE.run('verify:tokens', {pool: POOL_NAME}); + await DRE.run('verify:tokens', { pool: POOL_NAME }); } - if (network.includes('tenderly')) { + if (usingTenderly()) { const postDeployHead = DRE.tenderlyRPC.getHead(); console.log('Tenderly UUID', postDeployHead); } From 51ea7364e1b45c66d8fb7b32c1cc97d18a0d77ad Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 18:31:04 -0500 Subject: [PATCH 121/219] (Same functionality) Updated LP mainnet --- tasks/migrations/lp.mainnet.ts | 37 +++++++++++++--------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/tasks/migrations/lp.mainnet.ts b/tasks/migrations/lp.mainnet.ts index 70121c03..912f48b4 100644 --- a/tasks/migrations/lp.mainnet.ts +++ b/tasks/migrations/lp.mainnet.ts @@ -1,15 +1,13 @@ -import {task} from 'hardhat/config'; -import {ExternalProvider} from '@ethersproject/providers'; -import {checkVerification} from '../../helpers/etherscan-verification'; -import {ConfigNames} from '../../helpers/configuration'; -import {EthereumNetworkNames} from '../../helpers/types'; -import {printContracts} from '../../helpers/misc-utils'; +import { task } from 'hardhat/config'; +import { checkVerification } from '../../helpers/etherscan-verification'; +import { ConfigNames } from '../../helpers/configuration'; +import { printContracts } from '../../helpers/misc-utils'; +import { usingTenderly } from '../../helpers/tenderly-utils'; task('lp:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({verify}, DRE) => { + .setAction(async ({ verify }, DRE) => { const POOL_NAME = ConfigNames.Lp; - const network = DRE.network.name; await DRE.run('set-DRE'); // Prevent loss of gas verifying all the needed ENVs for Etherscan verification @@ -17,40 +15,33 @@ task('lp:mainnet', 'Deploy development enviroment') checkVerification(); } - if (network.includes('tenderly')) { - console.log('- Setting up Tenderly provider'); - await DRE.tenderlyRPC.initializeFork(); - const provider = new DRE.ethers.providers.Web3Provider(DRE.tenderlyRPC as any); - DRE.ethers.provider = provider; - } - console.log('Migration started\n'); console.log('1. Deploy address provider'); - await DRE.run('full:deploy-address-provider', {pool: POOL_NAME}); - + await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); + console.log('2. Deploy lending pool'); await DRE.run('full:deploy-lending-pool'); console.log('3. Deploy oracles'); - await DRE.run('full:deploy-oracles', {pool: POOL_NAME}); + await DRE.run('full:deploy-oracles', { pool: POOL_NAME }); console.log('4. Deploy Data Provider'); - await DRE.run('full:data-provider', {pool: POOL_NAME}); + await DRE.run('full:data-provider', { pool: POOL_NAME }); console.log('5. Initialize lending pool'); - await DRE.run('full:initialize-lending-pool', {pool: POOL_NAME}); + await DRE.run('full:initialize-lending-pool', { pool: POOL_NAME }); if (verify) { printContracts(); console.log('4. Veryfing contracts'); - await DRE.run('verify:general', {all: true, pool: POOL_NAME}); + await DRE.run('verify:general', { all: true, pool: POOL_NAME }); console.log('5. Veryfing aTokens and debtTokens'); - await DRE.run('verify:tokens', {pool: POOL_NAME}); + await DRE.run('verify:tokens', { pool: POOL_NAME }); } - if (network.includes('tenderly')) { + if (usingTenderly()) { const postDeployHead = DRE.tenderlyRPC.getHead(); console.log('Tenderly UUID', postDeployHead); } From 379761b56f9dc49279d29ac0a01042883bb1bbbe Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 18:50:24 -0500 Subject: [PATCH 122/219] Testing mumbai network deployment, Oracles fail --- helpers/configuration.ts | 7 +++++ helpers/contracts-helpers.ts | 6 +++- helpers/types.ts | 4 +++ markets/matic/commons.ts | 8 ++--- markets/matic/index.ts | 4 +-- package.json | 2 ++ tasks/migrations/matic.mainnet.ts | 50 +++++++++++++++++++++++++++++++ 7 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 tasks/migrations/matic.mainnet.ts diff --git a/helpers/configuration.ts b/helpers/configuration.ts index a9b780fb..894dc11f 100644 --- a/helpers/configuration.ts +++ b/helpers/configuration.ts @@ -9,6 +9,7 @@ import { import { getParamPerPool } from './contracts-helpers'; import AaveConfig from '../markets/aave'; import LpConfig from '../markets/lp'; +import MaticConfig from '../markets/matic' import { CommonsConfig } from '../markets/aave/commons'; import { DRE, filterMapBy } from './misc-utils'; import { tEthereumAddress } from './types'; @@ -19,6 +20,7 @@ export enum ConfigNames { Commons = 'Commons', Aave = 'Aave', Lp = 'Lp', + Matic = 'Matic', } export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => { @@ -27,6 +29,8 @@ export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => { return AaveConfig; case ConfigNames.Lp: return LpConfig; + case ConfigNames.Matic: + return MaticConfig; case ConfigNames.Commons: return CommonsConfig; default: @@ -47,6 +51,9 @@ export const getReservesConfigByPool = (pool: AavePools): iMultiPoolsAssets( - { kovan, ropsten, main, buidlerevm, coverage, tenderlyMain }: iParamsPerNetwork, + { kovan, ropsten, main, buidlerevm, coverage, tenderlyMain, matic, mumbai }: iParamsPerNetwork, network: eEthereumNetwork ) => { const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; @@ -154,6 +154,10 @@ export const getParamPerNetwork = ( return ropsten; case eEthereumNetwork.main: return main; + case eEthereumNetwork.matic: + return matic; + case eEthereumNetwork.mumbai: + return mumbai; case eEthereumNetwork.tenderlyMain: return tenderlyMain; } diff --git a/helpers/types.ts b/helpers/types.ts index 4c81d660..7e08399b 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -20,11 +20,14 @@ export enum EthereumNetworkNames { kovan = 'kovan', ropsten = 'ropsten', main = 'main', + matic = 'matic', + mumbai = 'mumbai', } export enum AavePools { proto = 'proto', lp = 'lp', + matic = 'matic', } export enum eContractid { @@ -394,6 +397,7 @@ export interface iParamsPerNetwork { export interface iParamsPerPool { [AavePools.proto]: T; [AavePools.lp]: T; + [AavePools.matic]: T; } export interface iBasicDistributionParams { diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index fb89e43a..78fb7d3d 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -134,7 +134,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', - [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.mumbai]: '0x569859d41499B4dDC28bfaA43915051FF0A38a6F', // TEMP [eEthereumNetwork.matic]: '', }, ProviderRegistryOwner: { @@ -145,7 +145,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', - [eEthereumNetwork.mumbai]: '', + [eEthereumNetwork.mumbai]: '0x18d9bA2baEfBdE0FF137C4ad031427EF205f1Fd9', // TEMP [eEthereumNetwork.matic]: '', }, LendingRateOracle: { @@ -271,7 +271,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.main]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.tenderlyMain]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', - [EthereumNetwork.mumbai]: ZERO_ADDRESS, // TEMP - [EthereumNetwork.matic]: ZERO_ADDRESS, // TEMP + [EthereumNetwork.mumbai]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', // TEMP + [EthereumNetwork.matic]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', // TEMP }, }; diff --git a/markets/matic/index.ts b/markets/matic/index.ts index f48b21d9..a75e257d 100644 --- a/markets/matic/index.ts +++ b/markets/matic/index.ts @@ -15,7 +15,7 @@ import { // POOL--SPECIFIC PARAMS // ---------------- -export const AaveConfig: IMaticConfiguration = { +export const MaticConfig: IMaticConfiguration = { ...CommonsConfig, MarketId: 'Matic Market', ProviderId: 3, // Unknown? @@ -68,4 +68,4 @@ export const AaveConfig: IMaticConfiguration = { }, }; -export default AaveConfig; +export default MaticConfig; diff --git a/package.json b/package.json index b2492041..5e2e3985 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "hardhat:ropsten": "hardhat--network ropsten", "hardhat:main": "hardhat --network main", "hardhat:docker": "hardhat --network hardhatevm_docker", + "hardhat:mumbai": "hardhat --network mumbai", "compile": "SKIP_LOAD=true hardhat compile", "console:fork": "MAINNET_FORK=true hardhat console", "test": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-aave/*.spec.ts", @@ -40,6 +41,7 @@ "aave:docker:full:migration": "npm run compile && npm run hardhat:docker -- aave:mainnet", "aave:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- aave:mainnet --verify", "lp:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- lp:mainnet --verify", + "matic:mumbai:full:migration": "npm run compile && npm run hardhat:mumbai matic:mainnet", "aave:kovan:full:initialize": "npm run hardhat:kovan -- full:initialize-lending-pool --verify --pool Aave", "aave:ropsten:full:migration": "npm run compile && npm run hardhat:ropsten -- aave:mainnet --verify", "aave:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- aave:mainnet", diff --git a/tasks/migrations/matic.mainnet.ts b/tasks/migrations/matic.mainnet.ts new file mode 100644 index 00000000..0c8efe3c --- /dev/null +++ b/tasks/migrations/matic.mainnet.ts @@ -0,0 +1,50 @@ +import { task } from 'hardhat/config'; +import { checkVerification } from '../../helpers/etherscan-verification'; +import { ConfigNames } from '../../helpers/configuration'; +import { printContracts } from '../../helpers/misc-utils'; +import { usingTenderly } from '../../helpers/tenderly-utils'; + +task('matic:mainnet', 'Deploy development enviroment') + .addFlag('verify', 'Verify contracts at Etherscan') + .setAction(async ({ verify }, DRE) => { + const POOL_NAME = ConfigNames.Matic; + await DRE.run('set-DRE'); + + // Prevent loss of gas verifying all the needed ENVs for Etherscan verification + if (verify) { + checkVerification(); + } + + console.log('Migration started\n'); + + console.log('1. Deploy address provider'); + await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); + + console.log('2. Deploy lending pool'); + await DRE.run('full:deploy-lending-pool'); + + 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. Initialize lending pool'); + await DRE.run('full:initialize-lending-pool', { pool: POOL_NAME }); + + if (verify) { + printContracts(); + console.log('4. Veryfing contracts'); + await DRE.run('verify:general', { all: true, pool: POOL_NAME }); + + console.log('5. Veryfing aTokens and debtTokens'); + await DRE.run('verify:tokens', { pool: POOL_NAME }); + } + + if (usingTenderly()) { + const postDeployHead = DRE.tenderlyRPC.getHead(); + console.log('Tenderly UUID', postDeployHead); + } + console.log('\nFinished migrations'); + printContracts(); + }); From 5e0005e32c5184f1a0c357a95dcd1ddf1b5025c7 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 21:58:10 -0500 Subject: [PATCH 123/219] Set Matic gas limit to 7.5 gwei & added task --- hardhat.config.ts | 2 +- package.json | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index ed0fa247..030a780d 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -49,7 +49,7 @@ const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number url: 'https://rpc-mainnet.matic.network', blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, gasMultiplier: DEFAULT_GAS_MUL, - gasPrice: DEFAULT_GAS_PRICE, + gasPrice: 7500000000, chainId: networkId, accounts: { mnemonic: MNEMONIC, diff --git a/package.json b/package.json index 5e2e3985..3119ccb2 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "hardhat:main": "hardhat --network main", "hardhat:docker": "hardhat --network hardhatevm_docker", "hardhat:mumbai": "hardhat --network mumbai", + "hardhat:matic": "hardhat --network matic", "compile": "SKIP_LOAD=true hardhat compile", "console:fork": "MAINNET_FORK=true hardhat console", "test": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-aave/*.spec.ts", @@ -42,6 +43,7 @@ "aave:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- aave:mainnet --verify", "lp:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- lp:mainnet --verify", "matic:mumbai:full:migration": "npm run compile && npm run hardhat:mumbai matic:mainnet", + "matic:matic:full:migration": "npm run compile && npm run hardhat:matic matic:mainnet", "aave:kovan:full:initialize": "npm run hardhat:kovan -- full:initialize-lending-pool --verify --pool Aave", "aave:ropsten:full:migration": "npm run compile && npm run hardhat:ropsten -- aave:mainnet --verify", "aave:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- aave:mainnet", From f9f29b312c33e14bdcf3e07f45eb47db43453b91 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 21:58:25 -0500 Subject: [PATCH 124/219] Added generic debt token deployments --- helpers/contracts-deployments.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 2406c065..c514ee27 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -321,7 +321,6 @@ export const deployStableDebtToken = async ( return instance; } - export const deployVariableDebtToken = async ( args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], @@ -346,6 +345,19 @@ export const deployVariableDebtToken = async ( return instance; } +export const deployGenericStableDebtToken = async () => withSaveAndVerify( + await new StableDebtTokenFactory(await getFirstSigner()).deploy(), + eContractid.StableDebtToken, + [], + false +); + +export const deployGenericVariableDebtToken = async () => withSaveAndVerify( + await new VariableDebtTokenFactory(await getFirstSigner()).deploy(), + eContractid.VariableDebtToken, + [], + false +); export const deployGenericAToken = async ( [poolAddress, underlyingAssetAddress, treasuryAddress, incentivesController, name, symbol]: [ From 1c16f9f074c37302a34339101bd852c450ebb5e6 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 21:58:39 -0500 Subject: [PATCH 125/219] COMMENTED OUT MATIC-BREAKING code --- helpers/init-helpers.ts | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 3f6ce5f4..308a3087 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -23,6 +23,8 @@ import { deployDelegationAwareATokenImpl, deployGenericAToken, deployGenericATokenImpl, + deployGenericStableDebtToken, + deployGenericVariableDebtToken, deployStableDebtToken, deployVariableDebtToken, } from './contracts-deployments'; @@ -102,17 +104,20 @@ export const initReservesByHelper = async ( let stableDebtTokenImplementationAddress = ""; let variableDebtTokenImplementationAddress = ""; - const tx1 = await waitForTx( - await stableAndVariableDeployer.initDeployment([ZERO_ADDRESS], ["1"]) - ); - tx1.events?.forEach((event, index) => { - stableDebtTokenImplementationAddress = event?.args?.stableToken; - variableDebtTokenImplementationAddress = event?.args?.variableToken; - rawInsertContractAddressInDb(`stableDebtTokenImpl`, stableDebtTokenImplementationAddress); - rawInsertContractAddressInDb(`variableDebtTokenImpl`, variableDebtTokenImplementationAddress); - }); + // NOT WORKING ON MATIC + // const tx1 = await waitForTx( + // await stableAndVariableDeployer.initDeployment([ZERO_ADDRESS], ["1"]) + // ); + // console.log(tx1.events); + // tx1.events?.forEach((event, index) => { + // stableDebtTokenImplementationAddress = event?.args?.stableToken; + // variableDebtTokenImplementationAddress = event?.args?.variableToken; + // rawInsertContractAddressInDb(`stableDebtTokenImpl`, stableDebtTokenImplementationAddress); + // rawInsertContractAddressInDb(`variableDebtTokenImpl`, variableDebtTokenImplementationAddress); + // }); //gasUsage = gasUsage.add(tx1.gasUsed); - + stableDebtTokenImplementationAddress = await (await deployGenericStableDebtToken()).address; + variableDebtTokenImplementationAddress = await (await deployGenericVariableDebtToken()).address; const aTokenImplementation = await deployGenericATokenImpl(verify); aTokenImplementationAddress = aTokenImplementation.address; From 8d831d5ad7ab93c273bbebced949c572d0e45238 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 21:58:52 -0500 Subject: [PATCH 126/219] Added deployment information --- markets/matic/commons.ts | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index 78fb7d3d..e908a97c 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -135,7 +135,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', [eEthereumNetwork.mumbai]: '0x569859d41499B4dDC28bfaA43915051FF0A38a6F', // TEMP - [eEthereumNetwork.matic]: '', + [eEthereumNetwork.matic]: '0x3E7803614113F4199bE15b9dC915FA2f4EDE902B', // TEMP }, ProviderRegistryOwner: { [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', @@ -146,7 +146,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', [eEthereumNetwork.mumbai]: '0x18d9bA2baEfBdE0FF137C4ad031427EF205f1Fd9', // TEMP - [eEthereumNetwork.matic]: '', + [eEthereumNetwork.matic]: '0x18d9bA2baEfBdE0FF137C4ad031427EF205f1Fd9', // TEMP }, LendingRateOracle: { [eEthereumNetwork.coverage]: '', @@ -207,8 +207,20 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.buidlerevm]: {}, - [eEthereumNetwork.matic]: {}, - [eEthereumNetwork.mumbai]: {}, + [eEthereumNetwork.matic]: { + DAI: '0x4746DeC9e833A82EC7C2C1356372CcF2cfcD2F3D', + USDC: '0xfE4A8cc5b5B2366C1B58Bea3858e81843581b2F7', + USDT: '0x0A6513e40db6EB1b165753AD52E80663aeA50545', + WBTC: '0xc907E116054Ad103354f2D350FD2514433D57F6f', + MATIC: '0xAB594600376Ec9fD91F8e885dADF0CE036862dE0', + }, + [eEthereumNetwork.mumbai]: { + DAI: ZERO_ADDRESS, + USDC: ZERO_ADDRESS, + USDT: ZERO_ADDRESS, + WBTC: ZERO_ADDRESS, + MATIC: ZERO_ADDRESS, + }, [EthereumNetwork.kovan]: {}, [EthereumNetwork.ropsten]: {}, [EthereumNetwork.main]: { @@ -260,7 +272,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0xc778417e063141139fce010982780140aa0cd5ab', [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', [eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - [EthereumNetwork.mumbai]: '', // No WETH gateway on L2 + [EthereumNetwork.mumbai]: '0x53CDb16B8C031B779e996406546614E5F05BC4Bf', // No WETH gateway on L2 [EthereumNetwork.matic]: '', // No WETH gateway on L2 }, ReserveFactorTreasuryAddress: { From 384f00f15e1093e27753705166d7e8a85d3944c4 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 19 Feb 2021 21:59:14 -0500 Subject: [PATCH 127/219] Fixed issues before deployment --- markets/matic/index.ts | 2 +- tasks/full/5_initialize.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/markets/matic/index.ts b/markets/matic/index.ts index a75e257d..8dbda72d 100644 --- a/markets/matic/index.ts +++ b/markets/matic/index.ts @@ -45,7 +45,7 @@ export const MaticConfig: IMaticConfiguration = { USDT: '0xB3abd1912F586fDFFa13606882c28E27913853d2', WBTC: '0x393E3512d45a956A628124665672312ea86930Ba', WETH: '0x53CDb16B8C031B779e996406546614E5F05BC4Bf', - MATIC: '0x0000000000000000000000000000000000001010 ', + MATIC: '0x0000000000000000000000000000000000001010', }, [EthereumNetwork.kovan]: {}, [EthereumNetwork.ropsten]: {}, diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 99725034..858bd77d 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -83,8 +83,9 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const wethAddress = await getWethAddress(poolConfig); const lendingPoolAddress = await addressesProvider.getLendingPool(); - - await deployWETHGateway([wethAddress, lendingPoolAddress]); + if (network != 'mumbai' && network != 'matic') { + await deployWETHGateway([wethAddress, lendingPoolAddress]); + } } catch (err) { console.error(err); exit(1); From e591ae4dfc94364834a6588021b7e1ba0dd7f4a5 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Sun, 21 Feb 2021 18:18:59 -0500 Subject: [PATCH 128/219] Updated MATIC prefix --- markets/matic/commons.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index e908a97c..74c45f9d 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -55,7 +55,7 @@ export const CommonsConfig: ICommonConfiguration = { ATokenNamePrefix: 'Aave Matic Market', StableDebtTokenNamePrefix: 'Aave Matic Market stable debt', VariableDebtTokenNamePrefix: 'Aave Matic Market variable debt', - SymbolPrefix: 'Matic', + SymbolPrefix: 'm', ProviderId: 0, // Overriden in index.ts ProtocolGlobalParams: { TokenDistributorPercentageBase: '10000', From ec4df02f847863c731ab96b639a522e5ef5fc4b4 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Sun, 21 Feb 2021 18:55:27 -0500 Subject: [PATCH 129/219] Fixed tests, moved MOCK_CHAINLING_AGGREGATORS_PRICES to constants.ts --- helpers/constants.ts | 40 +++++++++++++++++++++++ helpers/types.ts | 2 ++ markets/aave/commons.ts | 46 +-------------------------- markets/lp/commons.ts | 46 +-------------------------- markets/matic/commons.ts | 46 +-------------------------- test-suites/test-aave/__setup.spec.ts | 1 + test-suites/test-lp/__setup.spec.ts | 1 + 7 files changed, 47 insertions(+), 135 deletions(-) diff --git a/helpers/constants.ts b/helpers/constants.ts index 708fe98d..a48a3fee 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -28,3 +28,43 @@ export const TOKEN_DISTRIBUTOR_PERCENTAGE_BASE = '10000'; export const MOCK_USD_PRICE_IN_WEI = '5848466240000000'; export const USD_ADDRESS = '0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96'; export const AAVE_REFERRAL = '0'; + +export const MOCK_CHAINLINK_AGGREGATORS_PRICES = { + AAVE: oneEther.multipliedBy('0.003620948469').toFixed(), + BAT: oneEther.multipliedBy('0.00137893825230').toFixed(), + BUSD: oneEther.multipliedBy('0.00736484').toFixed(), + DAI: oneEther.multipliedBy('0.00369068412860').toFixed(), + ENJ: oneEther.multipliedBy('0.00029560').toFixed(), + KNC: oneEther.multipliedBy('0.001072').toFixed(), + LINK: oneEther.multipliedBy('0.009955').toFixed(), + MANA: oneEther.multipliedBy('0.000158').toFixed(), + MKR: oneEther.multipliedBy('2.508581').toFixed(), + REN: oneEther.multipliedBy('0.00065133').toFixed(), + SNX: oneEther.multipliedBy('0.00442616').toFixed(), + SUSD: oneEther.multipliedBy('0.00364714136416').toFixed(), + TUSD: oneEther.multipliedBy('0.00364714136416').toFixed(), + UNI: oneEther.multipliedBy('0.00536479').toFixed(), + USDC: oneEther.multipliedBy('0.00367714136416').toFixed(), + USDT: oneEther.multipliedBy('0.00369068412860').toFixed(), + WETH: oneEther.toFixed(), + WBTC: oneEther.multipliedBy('47.332685').toFixed(), + YFI: oneEther.multipliedBy('22.407436').toFixed(), + ZRX: oneEther.multipliedBy('0.001151').toFixed(), + UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), + UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), + UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), + UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), + UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), + UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), + BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + MATIC: oneEther.multipliedBy('0.003620948469').toFixed(), + USD: '5848466240000000', +}; diff --git a/helpers/types.ts b/helpers/types.ts index 7e08399b..b7b07980 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -343,6 +343,7 @@ export enum TokenContractId { UniWBTCUSDC = 'UniWBTCUSDC', UniYFIWETH = 'UniYFIWETH', BptWBTCWETH = 'BptWBTCWETH', + MATIC = 'MATIC', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { @@ -493,3 +494,4 @@ export interface ITokenAddress { } export type PoolConfiguration = ICommonConfiguration | IAaveConfiguration; + diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index 853c252e..efe71af3 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -1,51 +1,7 @@ import BigNumber from 'bignumber.js'; -import { oneEther, oneRay, RAY, ZERO_ADDRESS } from '../../helpers/constants'; +import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants'; import { ICommonConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; -const MOCK_CHAINLINK_AGGREGATORS_PRICES = { - AAVE: oneEther.multipliedBy('0.003620948469').toFixed(), - BAT: oneEther.multipliedBy('0.00137893825230').toFixed(), - BUSD: oneEther.multipliedBy('0.00736484').toFixed(), - DAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - ENJ: oneEther.multipliedBy('0.00029560').toFixed(), - KNC: oneEther.multipliedBy('0.001072').toFixed(), - LINK: oneEther.multipliedBy('0.009955').toFixed(), - MANA: oneEther.multipliedBy('0.000158').toFixed(), - MKR: oneEther.multipliedBy('2.508581').toFixed(), - REN: oneEther.multipliedBy('0.00065133').toFixed(), - SNX: oneEther.multipliedBy('0.00442616').toFixed(), - SUSD: oneEther.multipliedBy('0.00364714136416').toFixed(), - TUSD: oneEther.multipliedBy('0.00364714136416').toFixed(), - UNI: oneEther.multipliedBy('0.00536479').toFixed(), - USDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - USDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - WETH: oneEther.toFixed(), - WBTC: oneEther.multipliedBy('47.332685').toFixed(), - YFI: oneEther.multipliedBy('22.407436').toFixed(), - ZRX: oneEther.multipliedBy('0.001151').toFixed(), - // LpDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - // LpUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - // LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - // LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), - // LpWETH: oneEther.toFixed(), - UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), - UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), - UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), - UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), - UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), - BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - MATIC: oneEther.multipliedBy('0.003620948469').toFixed(), - USD: '5848466240000000', -}; // ---------------- // PROTOCOL GLOBAL PARAMS // ---------------- diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index 6e1fb16b..8f927258 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -1,51 +1,7 @@ import BigNumber from 'bignumber.js'; -import { oneEther, oneRay, RAY, ZERO_ADDRESS } from '../../helpers/constants'; +import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants'; import { ICommonConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; -const MOCK_CHAINLINK_AGGREGATORS_PRICES = { - AAVE: oneEther.multipliedBy('0.003620948469').toFixed(), - BAT: oneEther.multipliedBy('0.00137893825230').toFixed(), - BUSD: oneEther.multipliedBy('0.00736484').toFixed(), - DAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - ENJ: oneEther.multipliedBy('0.00029560').toFixed(), - KNC: oneEther.multipliedBy('0.001072').toFixed(), - LINK: oneEther.multipliedBy('0.009955').toFixed(), - MANA: oneEther.multipliedBy('0.000158').toFixed(), - MKR: oneEther.multipliedBy('2.508581').toFixed(), - REN: oneEther.multipliedBy('0.00065133').toFixed(), - SNX: oneEther.multipliedBy('0.00442616').toFixed(), - SUSD: oneEther.multipliedBy('0.00364714136416').toFixed(), - TUSD: oneEther.multipliedBy('0.00364714136416').toFixed(), - UNI: oneEther.multipliedBy('0.00536479').toFixed(), - USDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - USDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - WETH: oneEther.toFixed(), - WBTC: oneEther.multipliedBy('47.332685').toFixed(), - YFI: oneEther.multipliedBy('22.407436').toFixed(), - ZRX: oneEther.multipliedBy('0.001151').toFixed(), - // DAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - // USDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - // USDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - // WBTC: oneEther.multipliedBy('47.332685').toFixed(), - // WETH: oneEther.toFixed(), - UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), - UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), - UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), - UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), - UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), - BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - MATIC: oneEther.multipliedBy('0.003620948469').toFixed(), - USD: '5848466240000000', -}; // ---------------- // PROTOCOL GLOBAL PARAMS // ---------------- diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index 74c45f9d..c591556e 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -1,51 +1,7 @@ import BigNumber from 'bignumber.js'; -import { oneEther, oneRay, RAY, ZERO_ADDRESS } from '../../helpers/constants'; +import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants'; import { ICommonConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; -const MOCK_CHAINLINK_AGGREGATORS_PRICES = { - AAVE: oneEther.multipliedBy('0.003620948469').toFixed(), - BAT: oneEther.multipliedBy('0.00137893825230').toFixed(), - BUSD: oneEther.multipliedBy('0.00736484').toFixed(), - DAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - ENJ: oneEther.multipliedBy('0.00029560').toFixed(), - KNC: oneEther.multipliedBy('0.001072').toFixed(), - LINK: oneEther.multipliedBy('0.009955').toFixed(), - MANA: oneEther.multipliedBy('0.000158').toFixed(), - MKR: oneEther.multipliedBy('2.508581').toFixed(), - REN: oneEther.multipliedBy('0.00065133').toFixed(), - SNX: oneEther.multipliedBy('0.00442616').toFixed(), - SUSD: oneEther.multipliedBy('0.00364714136416').toFixed(), - TUSD: oneEther.multipliedBy('0.00364714136416').toFixed(), - UNI: oneEther.multipliedBy('0.00536479').toFixed(), - USDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - USDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - WETH: oneEther.toFixed(), - WBTC: oneEther.multipliedBy('47.332685').toFixed(), - YFI: oneEther.multipliedBy('22.407436').toFixed(), - ZRX: oneEther.multipliedBy('0.001151').toFixed(), - // LpDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - // LpUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - // LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - // LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), - // LpWETH: oneEther.toFixed(), - UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), - UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), - UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), - UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), - UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), - BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - MATIC: oneEther.multipliedBy('0.003620948469').toFixed(), - USD: '5848466240000000', -}; // ---------------- // PROTOCOL GLOBAL PARAMS // ---------------- diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index 006e0d74..1af7961d 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -185,6 +185,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, UniYFIWETH: mockTokens.UniYFIWETH.address, BptWBTCWETH: mockTokens.BptWBTCWETH.address, + MATIC: mockTokens.MATIC.address, USD: USD_ADDRESS, }, fallbackOracle diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-lp/__setup.spec.ts index 09c02efc..cf8d616a 100644 --- a/test-suites/test-lp/__setup.spec.ts +++ b/test-suites/test-lp/__setup.spec.ts @@ -185,6 +185,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, UniYFIWETH: mockTokens.UniYFIWETH.address, BptWBTCWETH: mockTokens.BptWBTCWETH.address, + MATIC: mockTokens.MATIC.address, USD: USD_ADDRESS, }, fallbackOracle From b3e14bc0339a3a999b7069c04be3f24dd0369033 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Sun, 21 Feb 2021 20:05:11 -0500 Subject: [PATCH 130/219] Fixed MATIC WETHGateway adaptation, uses wMATIC --- helpers/constants.ts | 2 +- helpers/types.ts | 6 +++--- markets/matic/commons.ts | 14 +++++++------- markets/matic/index.ts | 16 +++++++++------- tasks/full/5_initialize.ts | 6 +++--- test-suites/test-aave/__setup.spec.ts | 2 +- test-suites/test-lp/__setup.spec.ts | 2 +- 7 files changed, 25 insertions(+), 23 deletions(-) diff --git a/helpers/constants.ts b/helpers/constants.ts index a48a3fee..cb66e8a1 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -65,6 +65,6 @@ export const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), - MATIC: oneEther.multipliedBy('0.003620948469').toFixed(), + WMATIC: oneEther.multipliedBy('0.003620948469').toFixed(), USD: '5848466240000000', }; diff --git a/helpers/types.ts b/helpers/types.ts index b7b07980..00c7181b 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -230,7 +230,7 @@ export interface iAssetBase { UniWBTCUSDC: T; UniYFIWETH: T; BptWBTCWETH: T; - MATIC: T; + WMATIC: T; } export type iAssetsWithoutETH = Omit, 'ETH'>; @@ -292,7 +292,7 @@ export type iMaticPoolAssets = Pick< | 'USDT' | 'WBTC' | 'WETH' - | 'MATIC' + | 'WMATIC' >; export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; @@ -343,7 +343,7 @@ export enum TokenContractId { UniWBTCUSDC = 'UniWBTCUSDC', UniYFIWETH = 'UniYFIWETH', BptWBTCWETH = 'BptWBTCWETH', - MATIC = 'MATIC', + WMATIC = 'WMATIC', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index c591556e..83790bcb 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -48,7 +48,7 @@ export const CommonsConfig: ICommonConfiguration = { WBTC: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, - MATIC: { + WMATIC: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), // TEMP }, }, @@ -168,14 +168,14 @@ export const CommonsConfig: ICommonConfiguration = { USDC: '0xfE4A8cc5b5B2366C1B58Bea3858e81843581b2F7', USDT: '0x0A6513e40db6EB1b165753AD52E80663aeA50545', WBTC: '0xc907E116054Ad103354f2D350FD2514433D57F6f', - MATIC: '0xAB594600376Ec9fD91F8e885dADF0CE036862dE0', + WMATIC: '0xAB594600376Ec9fD91F8e885dADF0CE036862dE0', }, [eEthereumNetwork.mumbai]: { DAI: ZERO_ADDRESS, USDC: ZERO_ADDRESS, USDT: ZERO_ADDRESS, WBTC: ZERO_ADDRESS, - MATIC: ZERO_ADDRESS, + WMATIC: ZERO_ADDRESS, }, [EthereumNetwork.kovan]: {}, [EthereumNetwork.ropsten]: {}, @@ -184,14 +184,14 @@ export const CommonsConfig: ICommonConfiguration = { USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', - MATIC: ZERO_ADDRESS, + WMATIC: ZERO_ADDRESS, }, [EthereumNetwork.tenderlyMain]: { DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', - MATIC: ZERO_ADDRESS, + WMATIC: ZERO_ADDRESS, }, }, ReserveAssets: { @@ -228,8 +228,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0xc778417e063141139fce010982780140aa0cd5ab', [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', [eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - [EthereumNetwork.mumbai]: '0x53CDb16B8C031B779e996406546614E5F05BC4Bf', // No WETH gateway on L2 - [EthereumNetwork.matic]: '', // No WETH gateway on L2 + [EthereumNetwork.mumbai]: '0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889', // WMATIC address (untested) + [EthereumNetwork.matic]: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', // WMATIC address }, ReserveFactorTreasuryAddress: { [eEthereumNetwork.coverage]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', diff --git a/markets/matic/index.ts b/markets/matic/index.ts index 8dbda72d..ae935313 100644 --- a/markets/matic/index.ts +++ b/markets/matic/index.ts @@ -25,7 +25,7 @@ export const MaticConfig: IMaticConfiguration = { USDT: strategyUSDT, WBTC: strategyWBTC, WETH: strategyWETH, - MATIC: strategyMATIC, + WMATIC: strategyMATIC, }, ReserveAssets: { [eEthereumNetwork.buidlerevm]: {}, @@ -37,33 +37,35 @@ export const MaticConfig: IMaticConfiguration = { USDT: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F', WBTC: '0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6', WETH: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', - MATIC: '0x0000000000000000000000000000000000001010', + WMATIC: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', }, - [eEthereumNetwork.mumbai]: { // Mock tokens with a simple "mint" external function + [eEthereumNetwork.mumbai]: { // Mock tokens with a simple "mint" external function, except wmatic DAI: '0x13b3fda609C1eeb23b4F4b69257840760dCa6C4a', USDC: '0x52b63223994433FdE2F1350Ba69Dfd2779f06ABA', USDT: '0xB3abd1912F586fDFFa13606882c28E27913853d2', WBTC: '0x393E3512d45a956A628124665672312ea86930Ba', WETH: '0x53CDb16B8C031B779e996406546614E5F05BC4Bf', - MATIC: '0x0000000000000000000000000000000000001010', + WMATIC: '0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889', }, [EthereumNetwork.kovan]: {}, [EthereumNetwork.ropsten]: {}, - [EthereumNetwork.main]: { + [EthereumNetwork.main]: { + // WMATIC DOES NOT EXIST ON MAIN DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - MATIC: '0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', + WMATIC: '0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', }, [EthereumNetwork.tenderlyMain]: { + // WMATIC DOES NOT EXIST ON MAIN DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - MATIC: '0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', + WMATIC: '0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', }, }, }; diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 858bd77d..3c5bef85 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -83,9 +83,9 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const wethAddress = await getWethAddress(poolConfig); const lendingPoolAddress = await addressesProvider.getLendingPool(); - if (network != 'mumbai' && network != 'matic') { - await deployWETHGateway([wethAddress, lendingPoolAddress]); - } + + await deployWETHGateway([wethAddress, lendingPoolAddress]); + } catch (err) { console.error(err); exit(1); diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index 1af7961d..a244e5c9 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -185,7 +185,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, UniYFIWETH: mockTokens.UniYFIWETH.address, BptWBTCWETH: mockTokens.BptWBTCWETH.address, - MATIC: mockTokens.MATIC.address, + WMATIC: mockTokens.WMATIC.address, USD: USD_ADDRESS, }, fallbackOracle diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-lp/__setup.spec.ts index cf8d616a..69d54269 100644 --- a/test-suites/test-lp/__setup.spec.ts +++ b/test-suites/test-lp/__setup.spec.ts @@ -185,7 +185,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, UniYFIWETH: mockTokens.UniYFIWETH.address, BptWBTCWETH: mockTokens.BptWBTCWETH.address, - MATIC: mockTokens.MATIC.address, + WMATIC: mockTokens.WMATIC.address, USD: USD_ADDRESS, }, fallbackOracle From dacf441916826870671c9aa91cc8fcaf770ea36b Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 22 Feb 2021 12:30:26 +0100 Subject: [PATCH 131/219] Updated Weth gateway contract --- contracts/misc/WETHGateway.sol | 65 ++++++++++++---------- contracts/misc/interfaces/IWETHGateway.sol | 14 ++++- 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/contracts/misc/WETHGateway.sol b/contracts/misc/WETHGateway.sol index b90c9bbf..e2ef175c 100644 --- a/contracts/misc/WETHGateway.sol +++ b/contracts/misc/WETHGateway.sol @@ -18,20 +18,21 @@ contract WETHGateway is IWETHGateway, Ownable { using UserConfiguration for DataTypes.UserConfigurationMap; IWETH internal immutable WETH; - ILendingPool internal immutable POOL; - IAToken internal immutable aWETH; /** * @dev Sets the WETH address and the LendingPoolAddressesProvider address. Infinite approves lending pool. * @param weth Address of the Wrapped Ether contract - * @param pool Address of the LendingPool contract **/ - constructor(address weth, address pool) public { - ILendingPool poolInstance = ILendingPool(pool); + constructor(address weth) public { WETH = IWETH(weth); - POOL = poolInstance; - aWETH = IAToken(poolInstance.getReserveData(weth).aTokenAddress); - IWETH(weth).approve(pool, uint256(-1)); + } + + function authorizeLendingPool(address lendingPool) external onlyOwner { + require( + ILendingPool(lendingPool).getReserveData(address(WETH)).aTokenAddress != address(0), + 'AWETH_NOT_SETUP' + ); + WETH.approve(lendingPool, uint256(-1)); } /** @@ -40,9 +41,13 @@ contract WETHGateway is IWETHGateway, Ownable { * @param onBehalfOf address of the user who will receive the aTokens representing the deposit * @param referralCode integrators are assigned a referral code and can potentially receive rewards. **/ - function depositETH(address onBehalfOf, uint16 referralCode) external payable override { + function depositETH( + address lendingPool, + address onBehalfOf, + uint16 referralCode + ) external payable override { WETH.deposit{value: msg.value}(); - POOL.deposit(address(WETH), msg.value, onBehalfOf, referralCode); + ILendingPool(lendingPool).deposit(address(WETH), msg.value, onBehalfOf, referralCode); } /** @@ -50,7 +55,12 @@ contract WETHGateway is IWETHGateway, Ownable { * @param amount amount of aWETH to withdraw and receive native ETH * @param to address of the user who will receive native ETH */ - function withdrawETH(uint256 amount, address to) external override { + function withdrawETH( + address lendingPool, + uint256 amount, + address to + ) external override { + IAToken aWETH = IAToken(ILendingPool(lendingPool).getReserveData(address(WETH)).aTokenAddress); uint256 userBalance = aWETH.balanceOf(msg.sender); uint256 amountToWithdraw = amount; @@ -59,7 +69,7 @@ contract WETHGateway is IWETHGateway, Ownable { amountToWithdraw = userBalance; } aWETH.transferFrom(msg.sender, address(this), amountToWithdraw); - POOL.withdraw(address(WETH), amountToWithdraw, address(this)); + ILendingPool(lendingPool).withdraw(address(WETH), amountToWithdraw, address(this)); WETH.withdraw(amountToWithdraw); _safeTransferETH(to, amountToWithdraw); } @@ -71,12 +81,16 @@ contract WETHGateway is IWETHGateway, Ownable { * @param onBehalfOf the address for which msg.sender is repaying */ function repayETH( + address lendingPool, uint256 amount, uint256 rateMode, address onBehalfOf ) external payable override { (uint256 stableDebt, uint256 variableDebt) = - Helpers.getUserCurrentDebtMemory(onBehalfOf, POOL.getReserveData(address(WETH))); + Helpers.getUserCurrentDebtMemory( + onBehalfOf, + ILendingPool(lendingPool).getReserveData(address(WETH)) + ); uint256 paybackAmount = DataTypes.InterestRateMode(rateMode) == DataTypes.InterestRateMode.STABLE @@ -88,7 +102,7 @@ contract WETHGateway is IWETHGateway, Ownable { } require(msg.value >= paybackAmount, 'msg.value is less than repayment amount'); WETH.deposit{value: paybackAmount}(); - POOL.repay(address(WETH), msg.value, rateMode, onBehalfOf); + ILendingPool(lendingPool).repay(address(WETH), msg.value, rateMode, onBehalfOf); // refund remaining dust eth if (msg.value > paybackAmount) _safeTransferETH(msg.sender, msg.value - paybackAmount); @@ -101,11 +115,18 @@ contract WETHGateway is IWETHGateway, Ownable { * @param referralCode integrators are assigned a referral code and can potentially receive rewards */ function borrowETH( + address lendingPool, uint256 amount, uint256 interesRateMode, uint16 referralCode ) external override { - POOL.borrow(address(WETH), amount, interesRateMode, referralCode, msg.sender); + ILendingPool(lendingPool).borrow( + address(WETH), + amount, + interesRateMode, + referralCode, + msg.sender + ); WETH.withdraw(amount); _safeTransferETH(msg.sender, amount); } @@ -152,20 +173,6 @@ contract WETHGateway is IWETHGateway, Ownable { return address(WETH); } - /** - * @dev Get aWETH address used by WETHGateway - */ - function getAWETHAddress() external view returns (address) { - return address(aWETH); - } - - /** - * @dev Get LendingPool address used by WETHGateway - */ - function getLendingPoolAddress() external view returns (address) { - return address(POOL); - } - /** * @dev Only WETH contract is allowed to transfer ETH here. Prevent other addresses to send Ether to this contract. */ diff --git a/contracts/misc/interfaces/IWETHGateway.sol b/contracts/misc/interfaces/IWETHGateway.sol index c06471fb..78d913cd 100644 --- a/contracts/misc/interfaces/IWETHGateway.sol +++ b/contracts/misc/interfaces/IWETHGateway.sol @@ -2,17 +2,27 @@ pragma solidity 0.6.12; interface IWETHGateway { - function depositETH(address onBehalfOf, uint16 referralCode) external payable; + function depositETH( + address lendingPool, + address onBehalfOf, + uint16 referralCode + ) external payable; - function withdrawETH(uint256 amount, address onBehalfOf) external; + function withdrawETH( + address lendingPool, + uint256 amount, + address onBehalfOf + ) external; function repayETH( + address lendingPool, uint256 amount, uint256 rateMode, address onBehalfOf ) external payable; function borrowETH( + address lendingPool, uint256 amount, uint256 interesRateMode, uint16 referralCode From 1656f1c6a3a251d1a5bc258c4242fe7ab8b86040 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 22 Feb 2021 13:23:52 +0100 Subject: [PATCH 132/219] Added Weth gateway contract in config, updated deployment --- contracts/misc/WETHGateway.sol | 8 +- helpers/contracts-deployments.ts | 106 +++++++-------------- helpers/types.ts | 3 +- markets/aave/commons.ts | 10 +- markets/lp/commons.ts | 9 ++ package.json | 3 +- tasks/deployments/deploy-wethGateWay.ts | 21 ++++ tasks/dev/5_initialize.ts | 9 +- tasks/full/5_initialize.ts | 17 ++-- test-suites/test-aave/__setup.spec.ts | 11 ++- test-suites/test-aave/weth-gateway.spec.ts | 52 +++++----- test-suites/test-lp/__setup.spec.ts | 4 +- test-suites/test-lp/weth-gateway.spec.ts | 37 +++---- 13 files changed, 147 insertions(+), 143 deletions(-) create mode 100644 tasks/deployments/deploy-wethGateWay.ts diff --git a/contracts/misc/WETHGateway.sol b/contracts/misc/WETHGateway.sol index e2ef175c..336e8de2 100644 --- a/contracts/misc/WETHGateway.sol +++ b/contracts/misc/WETHGateway.sol @@ -28,16 +28,13 @@ contract WETHGateway is IWETHGateway, Ownable { } function authorizeLendingPool(address lendingPool) external onlyOwner { - require( - ILendingPool(lendingPool).getReserveData(address(WETH)).aTokenAddress != address(0), - 'AWETH_NOT_SETUP' - ); WETH.approve(lendingPool, uint256(-1)); } /** * @dev deposits WETH into the reserve, using native ETH. A corresponding amount of the overlying asset (aTokens) * is minted. + * @param lendingPool address of the targeted underlying lending pool * @param onBehalfOf address of the user who will receive the aTokens representing the deposit * @param referralCode integrators are assigned a referral code and can potentially receive rewards. **/ @@ -52,6 +49,7 @@ contract WETHGateway is IWETHGateway, Ownable { /** * @dev withdraws the WETH _reserves of msg.sender. + * @param lendingPool address of the targeted underlying lending pool * @param amount amount of aWETH to withdraw and receive native ETH * @param to address of the user who will receive native ETH */ @@ -76,6 +74,7 @@ contract WETHGateway is IWETHGateway, Ownable { /** * @dev repays a borrow on the WETH reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified). + * @param lendingPool address of the targeted underlying lending pool * @param amount the amount to repay, or uint256(-1) if the user wants to repay everything * @param rateMode the rate mode to repay * @param onBehalfOf the address for which msg.sender is repaying @@ -110,6 +109,7 @@ contract WETHGateway is IWETHGateway, Ownable { /** * @dev borrow WETH, unwraps to ETH and send both the ETH and DebtTokens to msg.sender, via `approveDelegation` and onBehalf argument in `LendingPool.borrow`. + * @param lendingPool address of the targeted underlying lending pool * @param amount the amount of ETH to borrow * @param interesRateMode the interest rate mode * @param referralCode integrators are assigned a referral code and can potentially receive rewards diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 2406c065..3c999cfb 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -310,18 +310,10 @@ export const deployStableDebtToken = async ( verify ); - await instance.initialize( - args[0], - args[1], - args[2], - "18", - args[3], - args[4] - ); + await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4]); return instance; -} - +}; export const deployVariableDebtToken = async ( args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], @@ -334,18 +326,10 @@ export const deployVariableDebtToken = async ( verify ); - await instance.initialize( - args[0], - args[1], - args[2], - "18", - args[3], - args[4] - ); + await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4]); return instance; -} - +}; export const deployGenericAToken = async ( [poolAddress, underlyingAssetAddress, treasuryAddress, incentivesController, name, symbol]: [ @@ -364,23 +348,22 @@ export const deployGenericAToken = async ( [], verify ); - + await instance.initialize( - poolAddress, + poolAddress, treasuryAddress, - underlyingAssetAddress, - incentivesController, - "18", - name, + underlyingAssetAddress, + incentivesController, + '18', + name, symbol ); return instance; }; -export const deployGenericATokenImpl = async ( - verify: boolean -) => withSaveAndVerify( +export const deployGenericATokenImpl = async (verify: boolean) => + withSaveAndVerify( await new ATokenFactory(await getFirstSigner()).deploy(), eContractid.AToken, [], @@ -404,23 +387,22 @@ export const deployDelegationAwareAToken = async ( [], verify ); - + await instance.initialize( pool, treasuryAddress, underlyingAssetAddress, incentivesController, - "18", + '18', name, symbol - ) + ); return instance; }; -export const deployDelegationAwareATokenImpl = async ( - verify: boolean -) => withSaveAndVerify( +export const deployDelegationAwareATokenImpl = async (verify: boolean) => + withSaveAndVerify( await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(), eContractid.DelegationAwareAToken, [], @@ -489,10 +471,7 @@ export const deployATokensAndRatesHelper = async ( verify ); -export const deployWETHGateway = async ( - args: [tEthereumAddress, tEthereumAddress], - verify?: boolean -) => +export const deployWETHGateway = async (args: [tEthereumAddress], verify?: boolean) => withSaveAndVerify( await new WETHGatewayFactory(await getFirstSigner()).deploy(...args), eContractid.WETHGateway, @@ -500,6 +479,14 @@ export const deployWETHGateway = async ( verify ); +export const authorizeWETHGateway = async ( + wethGateWay: tEthereumAddress, + lendingPool: tEthereumAddress +) => + await new WETHGatewayFactory(await getFirstSigner()) + .attach(wethGateWay) + .authorizeLendingPool(lendingPool); + export const deployMockStableDebtToken = async ( args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], verify?: boolean @@ -511,18 +498,10 @@ export const deployMockStableDebtToken = async ( verify ); - await instance.initialize( - args[0], - args[1], - args[2], - "18", - args[3], - args[4] - ); + await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4]); return instance; -} - +}; export const deployWETHMocked = async (verify?: boolean) => withSaveAndVerify( @@ -543,21 +522,13 @@ export const deployMockVariableDebtToken = async ( verify ); - await instance.initialize( - args[0], - args[1], - args[2], - "18", - args[3], - args[4] - ); + await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4]); return instance; -} - +}; export const deployMockAToken = async ( -args: [tEthereumAddress, tEthereumAddress, tEthereumAddress,tEthereumAddress, string, string], + args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], verify?: boolean ) => { const instance = await withSaveAndVerify( @@ -566,20 +537,11 @@ args: [tEthereumAddress, tEthereumAddress, tEthereumAddress,tEthereumAddress, st [], verify ); - - await instance.initialize( - args[0], - args[2], - args[1], - args[3], - "18", - args[4], - args[5], - ); + + await instance.initialize(args[0], args[2], args[1], args[3], '18', args[4], args[5]); return instance; -} - +}; export const deploySelfdestructTransferMock = async (verify?: boolean) => withSaveAndVerify( diff --git a/helpers/types.ts b/helpers/types.ts index 57a9bfd3..76557658 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -336,7 +336,7 @@ export interface IReserveParams extends IReserveBorrowParams, IReserveCollateral } export interface IInterestRateStrategyParams { - name: string, + name: string; optimalUtilizationRate: string; baseVariableBorrowRate: string; variableRateSlope1: string; @@ -452,6 +452,7 @@ export interface ICommonConfiguration { ReservesConfig: iMultiPoolsAssets; ATokenDomainSeparator: iParamsPerNetwork; WETH: iParamsPerNetwork; + WethGateway: iParamsPerNetwork; ReserveFactorTreasuryAddress: iParamsPerNetwork; } diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index 5571be27..395910d8 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -1,4 +1,3 @@ -import BigNumber from 'bignumber.js'; import { oneEther, oneRay, RAY, ZERO_ADDRESS } from '../../helpers/constants'; import { ICommonConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; @@ -196,6 +195,15 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', }, + WethGateway: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, TokenDistributor: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.buidlerevm]: '', diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index d29b7d29..e02676ae 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -199,6 +199,15 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', }, + WethGateway: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, TokenDistributor: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.buidlerevm]: '', diff --git a/package.json b/package.json index b2492041..8c78210e 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "test-permit": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-permit.spec.ts", "test-stable-and-atokens": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-transfer.spec.ts test-suites/test-aave/stable-token.spec.ts", "test-subgraph:scenarios": "hardhat --network hardhatevm_docker test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/subgraph-scenarios.spec.ts", - "test-weth": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/weth-gateway.spec.ts", + "test-weth:main": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/weth-gateway.spec.ts", + "test-weth:lp": "hardhat test test-suites/test-lp/__setup.spec.ts test-suites/test-lp/weth-gateway.spec.ts", "test-uniswap": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/uniswapAdapters*.spec.ts", "test:main:check-list": "MAINNET_FORK=true TS_NODE_TRANSPILE_ONLY=1 hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/mainnet/check-list.spec.ts", "dev:coverage": "buidler compile --force && buidler coverage --network coverage", diff --git a/tasks/deployments/deploy-wethGateWay.ts b/tasks/deployments/deploy-wethGateWay.ts new file mode 100644 index 00000000..83611efc --- /dev/null +++ b/tasks/deployments/deploy-wethGateWay.ts @@ -0,0 +1,21 @@ +import { task } from 'hardhat/config'; + +import { deployWETHGateway } from '../../helpers/contracts-deployments'; + +const CONTRACT_NAME = 'WETHGateway'; + +task(`deploy-${CONTRACT_NAME}`, `Deploys the ${CONTRACT_NAME} contract`) + .addParam('weth', 'Address of the weth token') + .addFlag('verify', `Verify ${CONTRACT_NAME} contract via Etherscan API.`) + .setAction(async ({ weth, verify }, localBRE) => { + await localBRE.run('set-DRE'); + + if (!localBRE.network.config.chainId) { + throw new Error('INVALID_CHAIN_ID'); + } + + const wethGateWay = await deployWETHGateway([weth], verify); + console.log(`${CONTRACT_NAME}.address`, wethGateWay.address); + + console.log(`\tFinished ${CONTRACT_NAME} deployment`); + }); diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index 983b7454..6c11ad6d 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -5,7 +5,10 @@ import { deployWalletBalancerProvider, deployAaveProtocolDataProvider, deployWETHGateway, + authorizeWETHGateway, } from '../../helpers/contracts-deployments'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { eEthereumNetwork } from '../../helpers/types'; import { ConfigNames, getReservesConfigByPool, @@ -30,12 +33,14 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ verify, pool }, localBRE) => { await localBRE.run('set-DRE'); + const network = localBRE.network.name; const poolConfig = loadPoolConfig(pool); const { ATokenNamePrefix, StableDebtTokenNamePrefix, VariableDebtTokenNamePrefix, SymbolPrefix, + WethGateway, } = poolConfig; const mockTokens = await getAllMockedTokens(); const allTokenAddresses = getAllTokenAddresses(mockTokens); @@ -87,6 +92,6 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') await insertContractAddressInDb(eContractid.AaveProtocolDataProvider, testHelpers.address); const lendingPoolAddress = await addressesProvider.getLendingPool(); - const wethAddress = await getWethAddress(poolConfig); - await deployWETHGateway([wethAddress, lendingPoolAddress]); + const gateWay = await getParamPerNetwork(WethGateway, network); + await authorizeWETHGateway(gateWay, lendingPoolAddress); }); diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 99725034..2e92ad90 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -4,6 +4,7 @@ import { deployLendingPoolCollateralManager, deployWalletBalancerProvider, deployWETHGateway, + authorizeWETHGateway, } from '../../helpers/contracts-deployments'; import { loadPoolConfig, @@ -29,14 +30,15 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') await localBRE.run('set-DRE'); const network = localBRE.network.name; const poolConfig = loadPoolConfig(pool); - const { + const { ATokenNamePrefix, StableDebtTokenNamePrefix, VariableDebtTokenNamePrefix, SymbolPrefix, ReserveAssets, ReservesConfig, - LendingPoolCollateralManager + LendingPoolCollateralManager, + WethGateway, } = poolConfig as ICommonConfiguration; const reserveAssets = await getParamPerNetwork(ReserveAssets, network); @@ -66,9 +68,10 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') ); await configureReservesByHelper(ReservesConfig, reserveAssets, testHelpers, admin); - - - let collateralManagerAddress = await getParamPerNetwork(LendingPoolCollateralManager, network); + let collateralManagerAddress = await getParamPerNetwork( + LendingPoolCollateralManager, + network + ); if (!collateralManagerAddress) { const collateralManager = await deployLendingPoolCollateralManager(verify); collateralManagerAddress = collateralManager.address; @@ -81,10 +84,10 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') await deployWalletBalancerProvider(verify); - const wethAddress = await getWethAddress(poolConfig); const lendingPoolAddress = await addressesProvider.getLendingPool(); - await deployWETHGateway([wethAddress, lendingPoolAddress]); + const gateWay = await getParamPerNetwork(WethGateway, network); + await authorizeWETHGateway(gateWay, lendingPoolAddress); } catch (err) { console.error(err); exit(1); diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index 006e0d74..9fc9d4f8 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -26,7 +26,9 @@ import { deployUniswapLiquiditySwapAdapter, deployUniswapRepayAdapter, deployFlashLiquidationAdapter, + authorizeWETHGateway, } from '../../helpers/contracts-deployments'; +import { eEthereumNetwork } from '../../helpers/types'; import { Signer } from 'ethers'; import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types'; import { MintableERC20 } from '../../types/MintableERC20'; @@ -95,7 +97,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const aaveAdmin = await deployer.getAddress(); const mockTokens = await deployAllMockTokens(deployer); - console.log("Deployed mocks"); + console.log('Deployed mocks'); const addressesProvider = await deployLendingPoolAddressesProvider(AaveConfig.MarketId); await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin)); @@ -191,7 +193,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { ); const mockAggregators = await deployAllMockAggregators(MOCK_CHAINLINK_AGGREGATORS_PRICES); - console.log("Mock aggs deployed"); + console.log('Mock aggs deployed'); const allTokenAddresses = Object.entries(mockTokens).reduce( (accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, tokenContract]) => ({ ...accum, @@ -237,7 +239,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const config = loadPoolConfig(ConfigNames.Aave); - const { + const { ATokenNamePrefix, StableDebtTokenNamePrefix, VariableDebtTokenNamePrefix, @@ -280,7 +282,8 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { await deployWalletBalancerProvider(); - await deployWETHGateway([mockTokens.WETH.address, lendingPoolAddress]); + const gateWay = await deployWETHGateway([mockTokens.WETH.address]); + await authorizeWETHGateway(gateWay.address, lendingPoolAddress); console.timeEnd('setup'); }; diff --git a/test-suites/test-aave/weth-gateway.spec.ts b/test-suites/test-aave/weth-gateway.spec.ts index 22939f5c..b1980d68 100644 --- a/test-suites/test-aave/weth-gateway.spec.ts +++ b/test-suites/test-aave/weth-gateway.spec.ts @@ -14,7 +14,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => const depositSize = parseEther('5'); const daiSize = parseEther('10000'); it('Deposit WETH via WethGateway and DAI', async () => { - const { users, wethGateway, aWETH } = testEnv; + const { users, wethGateway, aWETH, pool } = testEnv; const user = users[1]; const depositor = users[0]; @@ -22,10 +22,12 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Deposit liquidity with native ETH await wethGateway .connect(depositor.signer) - .depositETH(depositor.address, '0', { value: depositSize }); + .depositETH(pool.address, depositor.address, '0', { value: depositSize }); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + await wethGateway + .connect(user.signer) + .depositETH(pool.address, user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -53,7 +55,9 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Partial Withdraw and send native Ether to user const { gasUsed: withdrawGas } = await waitForTx( - await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) + await wethGateway + .connect(user.signer) + .withdrawETH(pool.address, partialWithdraw, user.address) ); const afterPartialEtherBalance = await user.signer.getBalance(); @@ -87,7 +91,9 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Full withdraw const { gasUsed: withdrawGas } = await waitForTx( - await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) + await wethGateway + .connect(user.signer) + .withdrawETH(pool.address, MAX_UINT_AMOUNT, user.address) ); const afterFullEtherBalance = await user.signer.getBalance(); @@ -111,7 +117,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Deposit with native ETH await wethGateway .connect(depositor.signer) - .depositETH(depositor.address, '0', { value: depositSize }); + .depositETH(pool.address, depositor.address, '0', { value: depositSize }); const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address @@ -142,7 +148,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) + .repayETH(pool.address, MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) ); const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); @@ -166,7 +172,9 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + await wethGateway + .connect(user.signer) + .depositETH(pool.address, user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -187,7 +195,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(partialPayment, '2', user.address, { value: partialPayment }) + .repayETH(pool.address, partialPayment, '2', user.address, { value: partialPayment }) ); const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); @@ -197,14 +205,14 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) + .repayETH(pool.address, MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); }); it('Borrow ETH via delegateApprove ETH and repays back', async () => { - const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; + const { users, wethGateway, aWETH, weth, helpersContract, pool } = testEnv; const borrowSize = parseEther('1'); const user = users[2]; const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( @@ -216,7 +224,9 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => expect(priorDebtBalance).to.be.eq(zero); // Deposit WETH with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + await wethGateway + .connect(user.signer) + .depositETH(pool.address, user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -229,7 +239,9 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => ); // Borrows ETH with WETH as collateral - await waitForTx(await wethGateway.connect(user.signer).borrowETH(borrowSize, '2', '0')); + await waitForTx( + await wethGateway.connect(user.signer).borrowETH(pool.address, borrowSize, '2', '0') + ); const debtBalance = await varDebtToken.balanceOf(user.address); @@ -239,7 +251,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) + .repayETH(pool.address, MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); @@ -297,18 +309,6 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => ).to.be.revertedWith('Fallback not allowed'); }); - it('Getters should retrieve correct state', async () => { - const { aWETH, weth, pool, wethGateway } = testEnv; - - const WETHAddress = await wethGateway.getWETHAddress(); - const aWETHAddress = await wethGateway.getAWETHAddress(); - const poolAddress = await wethGateway.getLendingPoolAddress(); - - expect(WETHAddress).to.be.equal(weth.address); - expect(aWETHAddress).to.be.equal(aWETH.address); - expect(poolAddress).to.be.equal(pool.address); - }); - it('Owner can do emergency token recovery', async () => { const { users, dai, wethGateway, deployer } = testEnv; const user = users[0]; diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-lp/__setup.spec.ts index 09c02efc..23843a6c 100644 --- a/test-suites/test-lp/__setup.spec.ts +++ b/test-suites/test-lp/__setup.spec.ts @@ -26,6 +26,7 @@ import { deployUniswapLiquiditySwapAdapter, deployUniswapRepayAdapter, deployFlashLiquidationAdapter, + authorizeWETHGateway } from '../../helpers/contracts-deployments'; import { Signer } from 'ethers'; import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types'; @@ -279,7 +280,8 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { await deployWalletBalancerProvider(); - await deployWETHGateway([mockTokens.WETH.address, lendingPoolAddress]); + const gateWay = await deployWETHGateway([mockTokens.WETH.address]); + await authorizeWETHGateway(gateWay.address, lendingPoolAddress); console.timeEnd('setup'); }; diff --git a/test-suites/test-lp/weth-gateway.spec.ts b/test-suites/test-lp/weth-gateway.spec.ts index b8a0216a..80a3b169 100644 --- a/test-suites/test-lp/weth-gateway.spec.ts +++ b/test-suites/test-lp/weth-gateway.spec.ts @@ -15,7 +15,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => const depositSize = parseEther('5'); const daiSize = parseEther('10000'); it('Deposit WETH via WethGateway and DAI', async () => { - const { users, wethGateway, aWETH } = testEnv; + const { users, wethGateway, aWETH, pool } = testEnv; const user = users[1]; const depositor = users[0]; @@ -23,10 +23,10 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Deposit liquidity with native ETH await wethGateway .connect(depositor.signer) - .depositETH(depositor.address, '0', { value: depositSize }); + .depositETH(pool.address, depositor.address, '0', { value: depositSize }); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + await wethGateway.connect(user.signer).depositETH(pool.address, user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -54,7 +54,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Partial Withdraw and send native Ether to user const { gasUsed: withdrawGas } = await waitForTx( - await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) + await wethGateway.connect(user.signer).withdrawETH(pool.address, partialWithdraw, user.address) ); const afterPartialEtherBalance = await user.signer.getBalance(); @@ -88,7 +88,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Full withdraw const { gasUsed: withdrawGas } = await waitForTx( - await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) + await wethGateway.connect(user.signer).withdrawETH(pool.address, MAX_UINT_AMOUNT, user.address) ); const afterFullEtherBalance = await user.signer.getBalance(); @@ -112,7 +112,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Deposit with native ETH await wethGateway .connect(depositor.signer) - .depositETH(depositor.address, '0', { value: depositSize }); + .depositETH(pool.address, depositor.address, '0', { value: depositSize }); const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address @@ -168,7 +168,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + await wethGateway.connect(user.signer).depositETH(pool.address, user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -189,7 +189,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(partialPayment, '2', user.address, { value: partialPayment }) + .repayETH(pool.address, partialPayment, '2', user.address, { value: partialPayment }) ); const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); @@ -199,14 +199,14 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) + .repayETH(pool.address, MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); }); it('Borrow ETH via delegateApprove ETH and repays back', async () => { - const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; + const { users, wethGateway, aWETH, weth, helpersContract, pool } = testEnv; const borrowSize = parseEther('1'); const user = users[2]; const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( @@ -218,7 +218,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => expect(priorDebtBalance).to.be.eq(zero); // Deposit WETH with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + await wethGateway.connect(user.signer).depositETH(pool.address, user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -231,7 +231,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => ); // Borrows ETH with WETH as collateral - await waitForTx(await wethGateway.connect(user.signer).borrowETH(borrowSize, '2', '0')); + await waitForTx(await wethGateway.connect(user.signer).borrowETH(pool.address, borrowSize, '2', '0')); const debtBalance = await varDebtToken.balanceOf(user.address); @@ -241,7 +241,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) + .repayETH(pool.address, MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); @@ -299,17 +299,6 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => ).to.be.revertedWith('Fallback not allowed'); }); - it('Getters should retrieve correct state', async () => { - const { aWETH, weth, pool, wethGateway } = testEnv; - - const WETHAddress = await wethGateway.getWETHAddress(); - const aWETHAddress = await wethGateway.getAWETHAddress(); - const poolAddress = await wethGateway.getLendingPoolAddress(); - - expect(WETHAddress).to.be.equal(weth.address); - expect(aWETHAddress).to.be.equal(aWETH.address); - expect(poolAddress).to.be.equal(pool.address); - }); it('Owner can do emergency token recovery', async () => { const { users, dai, wethGateway, deployer } = testEnv; From 0d94e8fa669d7faa3427d5872532b177c1c16ffd Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 22 Feb 2021 14:58:16 +0100 Subject: [PATCH 133/219] Added full script and config for kovan --- markets/aave/commons.ts | 2 +- package-lock.json | 25493 +++++++++++++++- tasks/deployments/deploy-wethGateWay.ts | 21 - tasks/full/5-deploy-wethGateWay.ts | 32 + .../full/{5_initialize.ts => 6-initialize.ts} | 6 +- tasks/migrations/aave.mainnet.ts | 9 +- tasks/verifications/1_general.ts | 5 +- 7 files changed, 25413 insertions(+), 155 deletions(-) delete mode 100644 tasks/deployments/deploy-wethGateWay.ts create mode 100644 tasks/full/5-deploy-wethGateWay.ts rename tasks/full/{5_initialize.ts => 6-initialize.ts} (93%) diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index 395910d8..36bf744b 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -199,7 +199,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.kovan]: '0xf99b8E67a0E044734B01EC4586D1c88C9a869718', [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '', [eEthereumNetwork.tenderlyMain]: '', diff --git a/package-lock.json b/package-lock.json index bbe177fa..129f12e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,25338 @@ { "name": "@aave/protocol-v2", "version": "1.0.1", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "@aave/protocol-v2", + "version": "1.0.1", + "license": "AGPLv3", + "dependencies": { + "tmp-promise": "^3.0.2" + }, + "devDependencies": { + "@nomiclabs/buidler": "^1.4.7", + "@nomiclabs/buidler-ethers": "2.0.0", + "@nomiclabs/buidler-etherscan": "^2.1.0", + "@nomiclabs/buidler-waffle": "2.0.0", + "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomiclabs/hardhat-waffle": "^2.0.0", + "@openzeppelin/contracts": "3.1.0", + "@tenderly/hardhat-tenderly": "^1.1.0-beta.3", + "@typechain/ethers-v4": "1.0.0", + "@typechain/ethers-v5": "^2.0.0", + "@typechain/truffle-v4": "2.0.2", + "@typechain/truffle-v5": "2.0.2", + "@typechain/web3-v1": "1.0.0", + "@types/chai": "4.2.11", + "@types/lowdb": "1.0.9", + "@types/mocha": "7.0.2", + "@types/node": "14.0.5", + "bignumber.js": "9.0.0", + "buidler-typechain": "0.1.1", + "chai": "4.2.0", + "chai-bignumber": "3.0.0", + "chai-bn": "^0.2.1", + "dotenv": "^8.2.0", + "eth-sig-util": "2.5.3", + "ethereum-waffle": "3.0.2", + "ethereumjs-util": "7.0.2", + "ethers": "^5.0.19", + "globby": "^11.0.1", + "hardhat": "^2.0.8", + "hardhat-gas-reporter": "^1.0.0", + "hardhat-typechain": "^0.3.3", + "husky": "^4.2.5", + "lowdb": "1.0.0", + "prettier": "^2.0.5", + "prettier-plugin-solidity": "^1.0.0-alpha.53", + "pretty-quick": "^2.0.1", + "solidity-coverage": "0.7.10", + "temp-hardhat-etherscan": "^2.0.2", + "ts-generator": "^0.1.1", + "ts-node": "^8.10.2", + "tslint": "^6.1.2", + "tslint-config-prettier": "^1.18.0", + "tslint-plugin-prettier": "^2.3.0", + "typechain": "^4.0.0", + "typescript": "^4.0.5" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "node_modules/@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@ensdomains/ens": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/@ensdomains/ens/-/ens-0.4.5.tgz", + "integrity": "sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.2", + "eth-ens-namehash": "^2.0.8", + "solc": "^0.4.20", + "testrpc": "0.0.1", + "web3-utils": "^1.0.0-beta.31" + } + }, + "node_modules/@ensdomains/ens/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/@ensdomains/ens/node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "node_modules/@ensdomains/ens/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@ensdomains/ens/node_modules/require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "node_modules/@ensdomains/ens/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/@ensdomains/ens/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@ensdomains/ens/node_modules/solc": { + "version": "0.4.26", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.26.tgz", + "integrity": "sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA==", + "dev": true, + "dependencies": { + "fs-extra": "^0.30.0", + "memorystream": "^0.3.1", + "require-from-string": "^1.1.0", + "semver": "^5.3.0", + "yargs": "^4.7.1" + }, + "bin": { + "solcjs": "solcjs" + } + }, + "node_modules/@ensdomains/ens/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "node_modules/@ensdomains/ens/node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "node_modules/@ensdomains/ens/node_modules/yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "dev": true, + "dependencies": { + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.0.3", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" + } + }, + "node_modules/@ensdomains/ens/node_modules/yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "dev": true, + "dependencies": { + "camelcase": "^3.0.0", + "lodash.assign": "^4.0.6" + } + }, + "node_modules/@ensdomains/resolver": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@ensdomains/resolver/-/resolver-0.2.4.tgz", + "integrity": "sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA==", + "dev": true + }, + "node_modules/@ethereum-waffle/chai": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/chai/-/chai-3.2.0.tgz", + "integrity": "sha512-3mvI7luX8FSAX2yjklSN8rw8F8RNaMzZDadDkS9JvmoM4khByGe3mDn8rVroneBAcFusXJfL6BEssGj5S4mD7Q==", + "dev": true, + "dependencies": { + "@ethereum-waffle/provider": "^3.2.0", + "ethers": "^5.0.0" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/@ethereum-waffle/compiler": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/compiler/-/compiler-3.2.0.tgz", + "integrity": "sha512-Tg8YjbcVKQkNwhbiBf9Z4kKPolPO0IB+iYwAdpXNwgyMOH74guIHhFGtKOCPoY4VXR75erGgeQIt2PzIn/szCA==", + "dev": true, + "dependencies": { + "@resolver-engine/imports": "^0.3.3", + "@resolver-engine/imports-fs": "^0.3.3", + "@types/mkdirp": "^0.5.2", + "@types/node-fetch": "^2.5.5", + "ethers": "^5.0.1", + "mkdirp": "^0.5.1", + "node-fetch": "^2.6.0", + "solc": "^0.6.3" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/@ethereum-waffle/ens": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/ens/-/ens-3.2.0.tgz", + "integrity": "sha512-n4EYJDLAwN2X+2EsZMasXRlz5gYp39Tmy18RU4f6ZdnTNuVNw1BNkCC9VzrQooHGvHLjKZFPvcl+FRfBO+Xcyw==", + "dev": true, + "dependencies": { + "@ensdomains/ens": "^0.4.4", + "@ensdomains/resolver": "^0.2.4", + "ethers": "^5.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/@ethereum-waffle/mock-contract": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/mock-contract/-/mock-contract-3.2.0.tgz", + "integrity": "sha512-TfBt9ka2DXVxxIBee3WB0gSLgWCo9ZegqcdXjCz0QGlu+dEhL8W3+aLDYQoyx3kwlecfNl8EQ1V7g7GH8wrlMg==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.0.1", + "ethers": "^5.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/@ethereum-waffle/provider": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/provider/-/provider-3.2.0.tgz", + "integrity": "sha512-U9KyjMKIZuK4gi2kzWIJkAXYjtg0aIlEQ0F4yKqHMRyqAiSM6M4VJgn6tHisxe3Ev9z/jSnutKT8dyAEwlIYdw==", + "dev": true, + "dependencies": { + "@ethereum-waffle/ens": "^3.2.0", + "ethers": "^5.0.1", + "ganache-core": "^2.10.2", + "patch-package": "^6.2.2", + "postinstall-postinstall": "^2.1.0" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/@ethersproject/abi": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz", + "integrity": "sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==", + "dev": true, + "dependencies": { + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/@ethersproject/abstract-provider": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.5.tgz", + "integrity": "sha512-i/CjElAkzV7vQBAeoz+IpjGfcFYEP9eD7j3fzZ0fzTq03DO7PPnR+xkEZ1IoDXGwDS+55aLM1xvLDwB/Lx6IOQ==", + "dev": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/networks": "^5.0.3", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/transactions": "^5.0.5", + "@ethersproject/web": "^5.0.6" + } + }, + "node_modules/@ethersproject/abstract-signer": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.7.tgz", + "integrity": "sha512-8W8gy/QutEL60EoMEpvxZ8MFAEWs/JvH5nmZ6xeLXoZvmBCasGmxqHdYjo2cxg0nevkPkq9SeenSsBBZSCx+SQ==", + "dev": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3" + } + }, + "node_modules/@ethersproject/address": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.5.tgz", + "integrity": "sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA==", + "dev": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/rlp": "^5.0.3", + "bn.js": "^4.4.0" + } + }, + "node_modules/@ethersproject/base64": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.4.tgz", + "integrity": "sha512-4KRykQ7BQMeOXfvio1YITwHjxwBzh92UoXIdzxDE1p53CK28bbHPdsPNYo0wl0El7lJAMpT2SOdL0hhbWRnyIA==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4" + } + }, + "node_modules/@ethersproject/basex": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.0.4.tgz", + "integrity": "sha512-ixIr/kKiAoSzOnSc777AGIOAhKai5Ivqr4HO/Gz+YG+xkfv6kqD6AW4ga9vM20Wwb0QBhh3LoRWTu4V1K+x9Ew==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/properties": "^5.0.3" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.8.tgz", + "integrity": "sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "bn.js": "^4.4.0" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.5.tgz", + "integrity": "sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ==", + "dev": true, + "dependencies": { + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.5.tgz", + "integrity": "sha512-foaQVmxp2+ik9FrLUCtVrLZCj4M3Ibgkqvh+Xw/vFRSerkjVSYePApaVE5essxhoSlF1U9oXfWY09QI2AXtgKA==", + "dev": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7" + } + }, + "node_modules/@ethersproject/contracts": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.0.5.tgz", + "integrity": "sha512-tFI255lFbmbqMkgnuyhDWHl3yWqttPlReplYuVvDCT/SuvBjLR4ad2uipBlh1fh5X1ipK9ettAoV4S0HKim4Kw==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.0.5", + "@ethersproject/abstract-provider": "^5.0.4", + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.6.tgz", + "integrity": "sha512-Gvh57v6BWhwnud6l7tMfQm32PRQ2DYx2WaAAQmAxAfYvmzUkpQCBstnGeNMXIL8/2wdkvcB2u+WZRWaZtsFuUQ==", + "dev": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.0.6", + "@ethersproject/address": "^5.0.5", + "@ethersproject/bignumber": "^5.0.8", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.4", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/@ethersproject/hdnode": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.0.5.tgz", + "integrity": "sha512-Ho4HZaK+KijE5adayvjAGusWMnT0mgwGa5hGMBofBOgX9nqiKf6Wxx68SXBGI1/L3rmKo6mlAjxUd8gefs0teQ==", + "dev": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/basex": "^5.0.3", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/pbkdf2": "^5.0.3", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/sha2": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4", + "@ethersproject/strings": "^5.0.4", + "@ethersproject/transactions": "^5.0.5", + "@ethersproject/wordlists": "^5.0.4" + } + }, + "node_modules/@ethersproject/json-wallets": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.0.7.tgz", + "integrity": "sha512-dgOn9JtGgjT28mDXs4LYY2rT4CzS6bG/rxoYuPq3TLHIf6nmvBcr33Fee6RrM/y8UAx4gyIkf6wb2cXsOctvQQ==", + "dev": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/address": "^5.0.4", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/hdnode": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/pbkdf2": "^5.0.3", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/random": "^5.0.3", + "@ethersproject/strings": "^5.0.4", + "@ethersproject/transactions": "^5.0.5", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.4.tgz", + "integrity": "sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "js-sha3": "0.5.7" + } + }, + "node_modules/@ethersproject/keccak256/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/@ethersproject/logger": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.6.tgz", + "integrity": "sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ==", + "dev": true + }, + "node_modules/@ethersproject/networks": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.4.tgz", + "integrity": "sha512-/wHDTRms5mpJ09BoDrbNdFWINzONe05wZRgohCXvEv39rrH/Gd/yAnct8wC0RsW3tmFOgjgQxuBvypIxuUynTw==", + "dev": true, + "dependencies": { + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/pbkdf2": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.0.4.tgz", + "integrity": "sha512-9jVBjHXQKfr9+3bkCg01a8Cd1H9e+7Kw3ZMIvAxD0lZtuzrXsJxm1hVwY9KA+PRUvgS/9tTP4viXQYwLAax7zg==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/sha2": "^5.0.3" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.4.tgz", + "integrity": "sha512-UdyX3GqBxFt15B0uSESdDNmhvEbK3ACdDXl2soshoPcneXuTswHDeA0LoPlnaZzhbgk4p6jqb4GMms5C26Qu6A==", + "dev": true, + "dependencies": { + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/providers": { + "version": "5.0.14", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.0.14.tgz", + "integrity": "sha512-K9QRRkkHWyprm3g4L8U9aPx5uyivznL4RYemkN2shCQumyGqFJ5SO+OtQrgebVm0JpGwFAUGugnhRUh49sjErw==", + "dev": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.0.4", + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/address": "^5.0.4", + "@ethersproject/basex": "^5.0.3", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/networks": "^5.0.3", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/random": "^5.0.3", + "@ethersproject/rlp": "^5.0.3", + "@ethersproject/sha2": "^5.0.3", + "@ethersproject/strings": "^5.0.4", + "@ethersproject/transactions": "^5.0.5", + "@ethersproject/web": "^5.0.6", + "bech32": "1.1.4", + "ws": "7.2.3" + } + }, + "node_modules/@ethersproject/providers/node_modules/ws": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", + "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==", + "dev": true, + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/@ethersproject/random": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.0.4.tgz", + "integrity": "sha512-AIZJhqs6Ba4/+U3lOjt3QZbP6b/kuuGLJUYFUonAgWmkTHwqsCwYnFvnHKQSUuHbXHvErp7WFXFlztx+yMn3kQ==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.4.tgz", + "integrity": "sha512-5qrrZad7VTjofxSsm7Zg/7Dr4ZOln4S2CqiDdOuTv6MBKnXj0CiBojXyuDy52M8O3wxH0CyE924hXWTDV1PQWQ==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/sha2": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.0.4.tgz", + "integrity": "sha512-0yFhf1mspxAfWdXXoPtK94adUeu1R7/FzAa+DfEiZTc76sz/vHXf0LSIazoR3znYKFny6haBxME+usbvvEcF3A==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "hash.js": "1.1.3" + } + }, + "node_modules/@ethersproject/sha2/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.5.tgz", + "integrity": "sha512-Z1wY7JC1HVO4CvQWY2TyTTuAr8xK3bJijZw1a9G92JEmKdv1j255R/0YLBBcFTl2J65LUjtXynNJ2GbArPGi5g==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "elliptic": "6.5.3" + } + }, + "node_modules/@ethersproject/solidity": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.0.5.tgz", + "integrity": "sha512-DMFQ0ouXmNVoKWbGEUFGi8Urli4SJip9jXafQyFHWPRr5oJUqDVkNfwcyC37k+mhBG93k7qrYXCH2xJnGEOxHg==", + "dev": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/sha2": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.5.tgz", + "integrity": "sha512-JED6WaIV00xM/gvj8vSnd+0VWtDYdidTmavFRCTQakqfz+4tDo6Jz5LHgG+dd45h7ah7ykCHW0C7ZXWEDROCXQ==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/transactions": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.6.tgz", + "integrity": "sha512-htsFhOD+NMBxx676A8ehSuwVV49iqpSB+CkjPZ02tpNew0K6p8g0CZ46Z1ZP946gIHAU80xQ0NACHYrjIUaCFA==", + "dev": true, + "dependencies": { + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/rlp": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4" + } + }, + "node_modules/@ethersproject/units": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.0.6.tgz", + "integrity": "sha512-tsJuy4mipppdmooukRfhXt8fGx9nxvfvG6Xdy0RDm7LzHsjghjwQ69m2bCpId6SDSR1Uq1cQ9irPiUBSyWolUA==", + "dev": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/wallet": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.0.7.tgz", + "integrity": "sha512-n2GX1+2Tc0qV8dguUcLkjNugINKvZY7u/5fEsn0skW9rz5+jHTR5IKMV6jSfXA+WjQT8UCNMvkI3CNcdhaPbTQ==", + "dev": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.0.4", + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/hdnode": "^5.0.4", + "@ethersproject/json-wallets": "^5.0.6", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/random": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4", + "@ethersproject/transactions": "^5.0.5", + "@ethersproject/wordlists": "^5.0.4" + } + }, + "node_modules/@ethersproject/web": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.9.tgz", + "integrity": "sha512-//QNlv1MSkOII1hv3+HQwWoiVFS+BMVGI0KYeUww4cyrEktnx1QIez5bTSab9s9fWTFaWKNmQNBwMbxAqPuYDw==", + "dev": true, + "dependencies": { + "@ethersproject/base64": "^5.0.3", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/@ethersproject/wordlists": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.0.5.tgz", + "integrity": "sha512-XA3ycFltVrCTQt04w5nHu3Xq5Z6HjqWsXaAYQHFdqtugyUsIumaO9S5MOwFFuUYTNkZUoT3jCRa/OBS+K4tLfA==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nomiclabs/buidler": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@nomiclabs/buidler/-/buidler-1.4.8.tgz", + "integrity": "sha512-OUnNWx+WXOJzueJCfyuEXu3qNMq1j9eGDDpgflpRwjPeiQQnvVzfbwrPjs0PlxOC3Xtmaxabtgek5wGxS1C7Ew==", + "dev": true, + "dependencies": { + "@nomiclabs/ethereumjs-vm": "^4.1.1", + "@sentry/node": "^5.18.1", + "@solidity-parser/parser": "^0.5.2", + "@types/bn.js": "^4.11.5", + "@types/lru-cache": "^5.1.0", + "abort-controller": "^3.0.0", + "ansi-escapes": "^4.3.0", + "chalk": "^2.4.2", + "chokidar": "^3.4.0", + "ci-info": "^2.0.0", + "debug": "^4.1.1", + "deepmerge": "^2.1.0", + "download": "^7.1.0", + "enquirer": "^2.3.0", + "env-paths": "^2.2.0", + "eth-sig-util": "^2.5.2", + "ethereum-cryptography": "^0.1.2", + "ethereumjs-abi": "^0.6.8", + "ethereumjs-account": "^3.0.0", + "ethereumjs-block": "^2.2.0", + "ethereumjs-common": "^1.3.2", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^6.1.0", + "find-up": "^2.1.0", + "fp-ts": "1.19.3", + "fs-extra": "^7.0.1", + "glob": "^7.1.3", + "io-ts": "1.10.4", + "is-installed-globally": "^0.2.0", + "lodash": "^4.17.11", + "merkle-patricia-tree": "^3.0.0", + "mocha": "^7.1.2", + "node-fetch": "^2.6.0", + "qs": "^6.7.0", + "raw-body": "^2.4.1", + "semver": "^6.3.0", + "slash": "^3.0.0", + "solc": "0.6.8", + "source-map-support": "^0.5.13", + "ts-essentials": "^2.0.7", + "tsort": "0.0.1", + "uuid": "^3.3.2", + "ws": "^7.2.1" + }, + "bin": { + "buidler": "internal/cli/cli.js", + "builder": "internal/cli/cli-with-a-typo.js" + }, + "engines": { + "node": ">=8.2.0" + } + }, + "node_modules/@nomiclabs/buidler-ethers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/buidler-ethers/-/buidler-ethers-2.0.0.tgz", + "integrity": "sha512-Lf5XLClEeWYo6jVrGAqGBAcKTOP6IAChAR4qcDS36BkQnWakoRKcoSbwhr2YmTNTRAvgDWTmjQYbV17udJ+Alw==", + "dev": true + }, + "node_modules/@nomiclabs/buidler-etherscan": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/buidler-etherscan/-/buidler-etherscan-2.1.0.tgz", + "integrity": "sha512-Rh1PGCtIVNU9zDSnLn6WlJDMBM9LXzkwNnzRFnTrMdA+Aa9nMVX7qwbAXG9pyIIsuqNH6MRfk7CDvi8aMoojng==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.0.2", + "@ethersproject/address": "^5.0.2", + "cbor": "^5.0.2", + "ethereumjs-abi": "^0.6.8", + "node-fetch": "^2.6.0", + "semver": "^6.3.0" + } + }, + "node_modules/@nomiclabs/buidler-waffle": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/buidler-waffle/-/buidler-waffle-2.0.0.tgz", + "integrity": "sha512-slGUjMmooIFehk1EMz+gSD07x6RVhp9aEHCmjk5MDm9FuV0+1IhPrk0DDl9ZKYlb5dgTRSWOqzIOXLXhnjmt0A==", + "dev": true, + "dependencies": { + "@types/sinon-chai": "^3.2.3", + "@types/web3": "1.0.19" + } + }, + "node_modules/@nomiclabs/buidler/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz", + "integrity": "sha512-+XwqoO941bILTO4KDLIUJ37U42ySxw6it7jyoi0tKv0/VUcOrWKF1TCQWMv6dBDRlxpPQd273n9o5SVlYYLRWQ==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "async-eventemitter": "^0.2.2", + "core-js-pure": "^3.0.1", + "ethereumjs-account": "^3.0.0", + "ethereumjs-block": "^2.2.2", + "ethereumjs-blockchain": "^4.0.3", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.2", + "ethereumjs-util": "^6.2.0", + "fake-merkle-patricia-tree": "^1.0.1", + "functional-red-black-tree": "^1.0.1", + "merkle-patricia-tree": "^2.3.2", + "rustbn.js": "~0.2.0", + "safe-buffer": "^5.1.1", + "util.promisify": "^1.0.0" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/@nomiclabs/hardhat-ethers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.0.tgz", + "integrity": "sha512-fIi6XP9PgKqwSNVcLDr6S5hvGlc21PendaLD5eGdXEXc9aYQ0OJX8Mk3evs+p78x7W9n9U3ZcKtTiGc1+YScDw==", + "dev": true + }, + "node_modules/@nomiclabs/hardhat-waffle": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.0.tgz", + "integrity": "sha512-CnG9JC0rgqa68LTgyETxBUEWYAovvNGVs5abqaXjG80eF7iMLjDjM8IjOM87siAaxaxFCf6VBMJmtueqVq7jZw==", + "dev": true, + "dependencies": { + "@types/sinon-chai": "^3.2.3", + "@types/web3": "1.0.19" + } + }, + "node_modules/@openzeppelin/contracts": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-3.1.0.tgz", + "integrity": "sha512-dVXDnUKxrAKLzPdCRkz+N8qsVkK1XxJ6kk3zuI6zaQmcKxN7CkizoDP7lXxcs/Mi2I0mxceTRjJBqlzFffLJrQ==", + "dev": true + }, + "node_modules/@resolver-engine/core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz", + "integrity": "sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ==", + "dev": true, + "dependencies": { + "debug": "^3.1.0", + "is-url": "^1.2.4", + "request": "^2.85.0" + } + }, + "node_modules/@resolver-engine/core/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@resolver-engine/fs": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@resolver-engine/fs/-/fs-0.3.3.tgz", + "integrity": "sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ==", + "dev": true, + "dependencies": { + "@resolver-engine/core": "^0.3.3", + "debug": "^3.1.0" + } + }, + "node_modules/@resolver-engine/fs/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@resolver-engine/imports": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@resolver-engine/imports/-/imports-0.3.3.tgz", + "integrity": "sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q==", + "dev": true, + "dependencies": { + "@resolver-engine/core": "^0.3.3", + "debug": "^3.1.0", + "hosted-git-info": "^2.6.0", + "path-browserify": "^1.0.0", + "url": "^0.11.0" + } + }, + "node_modules/@resolver-engine/imports-fs": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz", + "integrity": "sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA==", + "dev": true, + "dependencies": { + "@resolver-engine/fs": "^0.3.3", + "@resolver-engine/imports": "^0.3.3", + "debug": "^3.1.0" + } + }, + "node_modules/@resolver-engine/imports-fs/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@resolver-engine/imports/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@sentry/core": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.27.4.tgz", + "integrity": "sha512-IbI37cIZU/qBQouuUXaLbGF/9xYFp5STqmj1Gv64l0IZe4JnEp06V3yD5GxQ/mJ78vSfOqfwLooVCUw9FA61sQ==", + "dev": true, + "dependencies": { + "@sentry/hub": "5.27.4", + "@sentry/minimal": "5.27.4", + "@sentry/types": "5.27.4", + "@sentry/utils": "5.27.4", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/hub": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.27.4.tgz", + "integrity": "sha512-Ba1AqcjvSd2S+fpdXtXCrVXdrzq9E2Etb2eHUOkEYwSsq7StMOw7E8YHDPAo+to8zUbpMPz/Z9XGhFkyAbImGQ==", + "dev": true, + "dependencies": { + "@sentry/types": "5.27.4", + "@sentry/utils": "5.27.4", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/minimal": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.27.4.tgz", + "integrity": "sha512-biw5YfIQwvDoaRhLarfeRQ6MJ9UJOoDTmu8Kgg18prJy4rtfDowNJP0OBs5XAsTk6SWAXiE3g7vqUJBXgs7BWA==", + "dev": true, + "dependencies": { + "@sentry/hub": "5.27.4", + "@sentry/types": "5.27.4", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/node": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.27.4.tgz", + "integrity": "sha512-fv3FfQ6FiNV56LKk6t48oNw8qgf7X5fEhqhvKAoU7w+BL9AhChzh9v7sWn9ppDtRFE45tFfsZh0J/8ox5jpnfQ==", + "dev": true, + "dependencies": { + "@sentry/core": "5.27.4", + "@sentry/hub": "5.27.4", + "@sentry/tracing": "5.27.4", + "@sentry/types": "5.27.4", + "@sentry/utils": "5.27.4", + "cookie": "^0.4.1", + "https-proxy-agent": "^5.0.0", + "lru_map": "^0.3.3", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/tracing": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.27.4.tgz", + "integrity": "sha512-f3nG8ozCdcbFOzsnBCZ8w+/WfoNiAd0Ctr643L0rsFbaSzPWxbPMe3LNVrWwFVo6mHacG3/2HYmJ3CYMiWyTKQ==", + "dev": true, + "dependencies": { + "@sentry/hub": "5.27.4", + "@sentry/minimal": "5.27.4", + "@sentry/types": "5.27.4", + "@sentry/utils": "5.27.4", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/types": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.27.4.tgz", + "integrity": "sha512-41h3c7tgtSS8UBmfvEckSr+7V7/IVOjt/EiydyOd6s0N18zSFfGY5HdA6g+eFtIJK3DhWkUHCHZNanD5IY5YCQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/utils": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.27.4.tgz", + "integrity": "sha512-shV1I/q+Tob3hUxRj11DfMhe9PNDiv85hUUoRloZGGwu275dMwpswb2uwgSmjc2Ao4pnMKVx8TL1hC3kGLVHTQ==", + "dev": true, + "dependencies": { + "@sentry/types": "5.27.4", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@solidity-parser/parser": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.5.2.tgz", + "integrity": "sha512-uRyvnvVYmgNmTBpWDbBsH/0kPESQhQpEc4KsvMRLVzFJ1o1s0uIv0Y6Y9IB5vI1Dwz2CbS4X/y4Wyw/75cTFnQ==", + "dev": true + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@tenderly/hardhat-tenderly": { + "version": "1.1.0-beta.3", + "resolved": "https://registry.npmjs.org/@tenderly/hardhat-tenderly/-/hardhat-tenderly-1.1.0-beta.3.tgz", + "integrity": "sha512-CCiS3bBCc4MhOTI5oHRAuVy/Xan6/8oNnjiwbsRvG1hdUis+EL/UVwn5yrUM1qXQTPz/La3TvRkfEa/pq1gimw==", + "dev": true, + "dependencies": { + "axios": "^0.20.0", + "fs-extra": "^9.0.1", + "js-yaml": "^3.14.0" + } + }, + "node_modules/@tenderly/hardhat-tenderly/node_modules/fs-extra": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", + "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tenderly/hardhat-tenderly/node_modules/js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@tenderly/hardhat-tenderly/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "node_modules/@tenderly/hardhat-tenderly/node_modules/jsonfile/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@tenderly/hardhat-tenderly/node_modules/universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@truffle/error": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@truffle/error/-/error-0.0.7.tgz", + "integrity": "sha512-UIfVKsXSXocKnn5+RNklUXNoGd/JVj7V8KmC48TQzmjU33HQI86PX0JDS7SpHMHasI3w9X//1q7Lu7nZtj3Zzg==", + "dev": true + }, + "node_modules/@truffle/interface-adapter": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.3.3.tgz", + "integrity": "sha512-l3I4WFTfnBSIfG96IOBRtAIE6AHDAxcOUJE7W5zh9hocQwzQlGWc2yEyyTcLa0656TTM8RxaZZ2S/KdHHMvCaw==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.8", + "ethers": "^4.0.32", + "lodash": "^4.17.13", + "web3": "1.2.2" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/@types/node": { + "version": "12.19.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", + "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/ethers": { + "version": "4.0.48", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.48.tgz", + "integrity": "sha512-sZD5K8H28dOrcidzx9f8KYh8083n5BexIO3+SbE4jK83L85FxtpXZBCQdXb8gkg+7sBqomcLhhkU7UHL+F7I2g==", + "dev": true, + "dependencies": { + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "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" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/scrypt-js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/web3": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.2.tgz", + "integrity": "sha512-/ChbmB6qZpfGx6eNpczt5YSUBHEA5V2+iUCbn85EVb3Zv6FVxrOo5Tv7Lw0gE2tW7EEjASbCyp3mZeiZaCCngg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@types/node": "^12.6.1", + "web3-bzz": "1.2.2", + "web3-core": "1.2.2", + "web3-eth": "1.2.2", + "web3-eth-personal": "1.2.2", + "web3-net": "1.2.2", + "web3-shh": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/web3-utils/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/@truffle/provider": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@truffle/provider/-/provider-0.1.19.tgz", + "integrity": "sha512-ke8iQmzW4Y99+8iff8xQcc+mCNU4AkwtaZ/iSpmVD8qpLytw8/DSNCm0RiEz9/+I93Q1zqI4Jnij/rXnkS2Njw==", + "dev": true, + "dependencies": { + "@truffle/error": "^0.0.7", + "@truffle/interface-adapter": "^0.3.0", + "web3": "1.2.1" + } + }, + "node_modules/@truffle/provider/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@truffle/provider/node_modules/@types/node": { + "version": "10.17.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", + "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@truffle/provider/node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@truffle/provider/node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@truffle/provider/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/@truffle/provider/node_modules/ethers": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", + "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", + "dev": true, + "dependencies": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.3", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/@truffle/provider/node_modules/ethers/node_modules/elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "dev": true, + "dependencies": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/@truffle/provider/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@truffle/provider/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@truffle/provider/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@truffle/provider/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@truffle/provider/node_modules/scrypt-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", + "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/semver": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz", + "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@truffle/provider/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/web3": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.1.tgz", + "integrity": "sha512-nNMzeCK0agb5i/oTWNdQ1aGtwYfXzHottFP2Dz0oGIzavPMGSKyVlr8ibVb1yK5sJBjrWVnTdGaOC2zKDFuFRw==", + "dev": true, + "dependencies": { + "web3-bzz": "1.2.1", + "web3-core": "1.2.1", + "web3-eth": "1.2.1", + "web3-eth-personal": "1.2.1", + "web3-net": "1.2.1", + "web3-shh": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-bzz": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.1.tgz", + "integrity": "sha512-LdOO44TuYbGIPfL4ilkuS89GQovxUpmLz6C1UC7VYVVRILeZS740FVB3j9V4P4FHUk1RenaDfKhcntqgVCHtjw==", + "dev": true, + "dependencies": { + "got": "9.6.0", + "swarm-js": "0.1.39", + "underscore": "1.9.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.1.tgz", + "integrity": "sha512-5ODwIqgl8oIg/0+Ai4jsLxkKFWJYE0uLuE1yUKHNVCL4zL6n3rFjRMpKPokd6id6nJCNgeA64KdWQ4XfpnjdMg==", + "dev": true, + "dependencies": { + "web3-core-helpers": "1.2.1", + "web3-core-method": "1.2.1", + "web3-core-requestmanager": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-core-helpers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.1.tgz", + "integrity": "sha512-Gx3sTEajD5r96bJgfuW377PZVFmXIH4TdqDhgGwd2lZQCcMi+DA4TgxJNJGxn0R3aUVzyyE76j4LBrh412mXrw==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-eth-iban": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-core-method": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.1.tgz", + "integrity": "sha512-Ghg2WS23qi6Xj8Od3VCzaImLHseEA7/usvnOItluiIc5cKs00WYWsNy2YRStzU9a2+z8lwQywPYp0nTzR/QXdQ==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.1", + "web3-core-promievent": "1.2.1", + "web3-core-subscriptions": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-core-promievent": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.1.tgz", + "integrity": "sha512-IVUqgpIKoeOYblwpex4Hye6npM0aMR+kU49VP06secPeN0rHMyhGF0ZGveWBrGvf8WDPI7jhqPBFIC6Jf3Q3zw==", + "dev": true, + "dependencies": { + "any-promise": "1.3.0", + "eventemitter3": "3.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-core-requestmanager": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.1.tgz", + "integrity": "sha512-xfknTC69RfYmLKC+83Jz73IC3/sS2ZLhGtX33D4Q5nQ8yc39ElyAolxr9sJQS8kihOcM6u4J+8gyGMqsLcpIBg==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.1", + "web3-providers-http": "1.2.1", + "web3-providers-ipc": "1.2.1", + "web3-providers-ws": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-core-subscriptions": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.1.tgz", + "integrity": "sha512-nmOwe3NsB8V8UFsY1r+sW6KjdOS68h8nuh7NzlWxBQT/19QSUGiERRTaZXWu5BYvo1EoZRMxCKyCQpSSXLc08g==", + "dev": true, + "dependencies": { + "eventemitter3": "3.1.2", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.1.tgz", + "integrity": "sha512-/2xly4Yry5FW1i+uygPjhfvgUP/MS/Dk+PDqmzp5M88tS86A+j8BzKc23GrlA8sgGs0645cpZK/999LpEF5UdA==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core": "1.2.1", + "web3-core-helpers": "1.2.1", + "web3-core-method": "1.2.1", + "web3-core-subscriptions": "1.2.1", + "web3-eth-abi": "1.2.1", + "web3-eth-accounts": "1.2.1", + "web3-eth-contract": "1.2.1", + "web3-eth-ens": "1.2.1", + "web3-eth-iban": "1.2.1", + "web3-eth-personal": "1.2.1", + "web3-net": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-abi": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.1.tgz", + "integrity": "sha512-jI/KhU2a/DQPZXHjo2GW0myEljzfiKOn+h1qxK1+Y9OQfTcBMxrQJyH5AP89O6l6NZ1QvNdq99ThAxBFoy5L+g==", + "dev": true, + "dependencies": { + "ethers": "4.0.0-beta.3", + "underscore": "1.9.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-accounts": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.1.tgz", + "integrity": "sha512-26I4qq42STQ8IeKUyur3MdQ1NzrzCqPsmzqpux0j6X/XBD7EjZ+Cs0lhGNkSKH5dI3V8CJasnQ5T1mNKeWB7nQ==", + "dev": true, + "dependencies": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "scryptsy": "2.1.0", + "semver": "6.2.0", + "underscore": "1.9.1", + "uuid": "3.3.2", + "web3-core": "1.2.1", + "web3-core-helpers": "1.2.1", + "web3-core-method": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-accounts/node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-contract": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.1.tgz", + "integrity": "sha512-kYFESbQ3boC9bl2rYVghj7O8UKMiuKaiMkxvRH5cEDHil8V7MGEGZNH0slSdoyeftZVlaWSMqkRP/chfnKND0g==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core": "1.2.1", + "web3-core-helpers": "1.2.1", + "web3-core-method": "1.2.1", + "web3-core-promievent": "1.2.1", + "web3-core-subscriptions": "1.2.1", + "web3-eth-abi": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-ens": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.1.tgz", + "integrity": "sha512-lhP1kFhqZr2nnbu3CGIFFrAnNxk2veXpOXBY48Tub37RtobDyHijHgrj+xTh+mFiPokyrapVjpFsbGa+Xzye4Q==", + "dev": true, + "dependencies": { + "eth-ens-namehash": "2.0.8", + "underscore": "1.9.1", + "web3-core": "1.2.1", + "web3-core-helpers": "1.2.1", + "web3-core-promievent": "1.2.1", + "web3-eth-abi": "1.2.1", + "web3-eth-contract": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-iban": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.1.tgz", + "integrity": "sha512-9gkr4QPl1jCU+wkgmZ8EwODVO3ovVj6d6JKMos52ggdT2YCmlfvFVF6wlGLwi0VvNa/p+0BjJzaqxnnG/JewjQ==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-personal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.1.tgz", + "integrity": "sha512-RNDVSiaSoY4aIp8+Hc7z+X72H7lMb3fmAChuSBADoEc7DsJrY/d0R5qQDK9g9t2BO8oxgLrLNyBP/9ub2Hc6Bg==", + "dev": true, + "dependencies": { + "web3-core": "1.2.1", + "web3-core-helpers": "1.2.1", + "web3-core-method": "1.2.1", + "web3-net": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-net": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.1.tgz", + "integrity": "sha512-Yt1Bs7WgnLESPe0rri/ZoPWzSy55ovioaP35w1KZydrNtQ5Yq4WcrAdhBzcOW7vAkIwrsLQsvA+hrOCy7mNauw==", + "dev": true, + "dependencies": { + "web3-core": "1.2.1", + "web3-core-method": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-providers-http": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.1.tgz", + "integrity": "sha512-BDtVUVolT9b3CAzeGVA/np1hhn7RPUZ6YYGB/sYky+GjeO311Yoq8SRDUSezU92x8yImSC2B+SMReGhd1zL+bQ==", + "dev": true, + "dependencies": { + "web3-core-helpers": "1.2.1", + "xhr2-cookies": "1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-providers-ipc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.1.tgz", + "integrity": "sha512-oPEuOCwxVx8L4CPD0TUdnlOUZwGBSRKScCz/Ws2YHdr9Ium+whm+0NLmOZjkjQp5wovQbyBzNa6zJz1noFRvFA==", + "dev": true, + "dependencies": { + "oboe": "2.1.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-providers-ws": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.1.tgz", + "integrity": "sha512-oqsQXzu+ejJACVHy864WwIyw+oB21nw/pI65/sD95Zi98+/HQzFfNcIFneF1NC4bVF3VNX4YHTNq2I2o97LAiA==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.1", + "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-shh": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.1.tgz", + "integrity": "sha512-/3Cl04nza5kuFn25bV3FJWa0s3Vafr5BlT933h26xovQ6HIIz61LmvNQlvX1AhFL+SNJOTcQmK1SM59vcyC8bA==", + "dev": true, + "dependencies": { + "web3-core": "1.2.1", + "web3-core-method": "1.2.1", + "web3-core-subscriptions": "1.2.1", + "web3-net": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.1.tgz", + "integrity": "sha512-Mrcn3l58L+yCKz3zBryM6JZpNruWuT0OCbag8w+reeNROSGVlXzUQkU+gtAwc9JCZ7tKUyg67+2YUGqUjVcyBA==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typechain/ethers-v4": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v4/-/ethers-v4-1.0.0.tgz", + "integrity": "sha512-tN9XV0ezbLaEuK6jC5gW6AiH4ihq9lMl1ifJr700oBjknKKNDO6jUSzUE56gJzhW/fuyGsb4zsCHwf3JCkBd9w==", + "dev": true + }, + "node_modules/@typechain/ethers-v5": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz", + "integrity": "sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw==", + "dev": true, + "dependencies": { + "ethers": "^5.0.2" + } + }, + "node_modules/@typechain/truffle-v4": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@typechain/truffle-v4/-/truffle-v4-2.0.2.tgz", + "integrity": "sha512-YoJAzgQZeark7lwInLnJ3u14JO980W5mVzFUkZny40+/WSPlox5Sa5IWLkULrgwkEWoiLA2sTpJ2tE7nCtSC2Q==", + "dev": true + }, + "node_modules/@typechain/truffle-v5": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@typechain/truffle-v5/-/truffle-v5-2.0.2.tgz", + "integrity": "sha512-g4N2kfol1S3g/QUkmpzukCGZiKWUdXsSms1be/+W4+R0DPMz1Q/76tY+C6bD7G/KeLhkiDKcnZFmNVNcAgjIfQ==", + "dev": true + }, + "node_modules/@typechain/web3-v1": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@typechain/web3-v1/-/web3-v1-1.0.0.tgz", + "integrity": "sha512-MM8PmsblePaxy5BCYEuPtR4ajigPf504VRQzZgFYqs6KuFnJxbOjF8jNYT12P6UvUX7us75Wc78QdbvOHbb4hA==", + "dev": true + }, + "node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/chai": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.11.tgz", + "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", + "dev": true + }, + "node_modules/@types/concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-OU2+C7X+5Gs42JZzXoto7yOQ0A0=", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/form-data": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", + "integrity": "sha1-yayFsqX9GENbjIXZ7LUObWyJP/g=", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.14.165", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.165.tgz", + "integrity": "sha512-tjSSOTHhI5mCHTy/OOXYIhi2Wt1qcbHmuXD1Ha7q70CgI/I71afO4XtLb/cVexki1oVYchpul/TOuu3Arcdxrg==", + "dev": true + }, + "node_modules/@types/lowdb": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/lowdb/-/lowdb-1.0.9.tgz", + "integrity": "sha512-LBRG5EPXFOJDoJc9jACstMhtMP+u+UkPYllBeGQXXKiaHc+uzJs9+/Aynb/5KkX33DtrIiKyzNVTPQc/4RcD6A==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lru-cache": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.0.tgz", + "integrity": "sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "node_modules/@types/mkdirp": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz", + "integrity": "sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/mocha": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", + "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "14.0.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.5.tgz", + "integrity": "sha512-90hiq6/VqtQgX8Sp0EzeIsv3r+ellbGj4URKj5j30tLlZvRUpnAe9YbYnjl3pJM93GyXU0tghHhvXHq+5rnCKA==", + "dev": true + }, + "node_modules/@types/node-fetch": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", + "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/pbkdf2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", + "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/prettier": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.5.tgz", + "integrity": "sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ==", + "dev": true + }, + "node_modules/@types/qs": { + "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 + }, + "node_modules/@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/secp256k1": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", + "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/sinon": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.8.tgz", + "integrity": "sha512-IVnI820FZFMGI+u1R+2VdRaD/82YIQTdqLYC9DLPszZuynAJDtCvCtCs3bmyL66s7FqRM3+LPX7DhHnVTaagDw==", + "dev": true, + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinon-chai": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.5.tgz", + "integrity": "sha512-bKQqIpew7mmIGNRlxW6Zli/QVyc3zikpGzCa797B/tRnD9OtHvZ/ts8sYXV+Ilj9u3QRaUEM8xrjgd1gwm1BpQ==", + "dev": true, + "dependencies": { + "@types/chai": "*", + "@types/sinon": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", + "integrity": "sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==", + "dev": true + }, + "node_modules/@types/underscore": { + "version": "1.10.24", + "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.10.24.tgz", + "integrity": "sha512-T3NQD8hXNW2sRsSbLNjF/aBo18MyJlbw0lSpQHB/eZZtScPdexN4HSa8cByYwTw9Wy7KuOFr81mlDQcQQaZ79w==", + "dev": true + }, + "node_modules/@types/web3": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/@types/web3/-/web3-1.0.19.tgz", + "integrity": "sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A==", + "dev": true, + "dependencies": { + "@types/bn.js": "*", + "@types/underscore": "*" + } + }, + "node_modules/@web3-js/scrypt-shim": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz", + "integrity": "sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "scryptsy": "^2.1.0", + "semver": "^6.3.0" + } + }, + "node_modules/@web3-js/websocket": { + "version": "1.0.30", + "resolved": "https://registry.npmjs.org/@web3-js/websocket/-/websocket-1.0.30.tgz", + "integrity": "sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "nan": "^2.14.0", + "typedarray-to-buffer": "^3.1.5", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@web3-js/websocket/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@web3-js/websocket/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/abstract-leveldown/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/address": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", + "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", + "dev": true, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true, + "engines": { + "node": ">=0.3.0" + } + }, + "node_modules/aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=", + "dev": true + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "dependencies": { + "type-fest": "^0.11.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/antlr4": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.8.0.tgz", + "integrity": "sha512-en/MxQ4OkPgGJQ3wD/muzj1uDnFSzdFIhc2+c6bHZokWkuBb6RRvFjpWhPxWLbgQvaEzldJZ0GSQpfSAaE3hqg==", + "dev": true + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/archive-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", + "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", + "dev": true, + "dependencies": { + "file-type": "^4.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/archive-type/node_modules/file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/async-eventemitter": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", + "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", + "dev": true, + "dependencies": { + "async": "^2.4.0" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "dev": true + }, + "node_modules/axios": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz", + "integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.10.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base-x": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", + "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "dev": true + }, + "node_modules/bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dev": true, + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/bl/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/bl/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/bl/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/blakejs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", + "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/body-parser/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-rsa/node_modules/bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "dev": true, + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/buffer-to-arraybuffer": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", + "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=", + "dev": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "node_modules/buidler-typechain": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buidler-typechain/-/buidler-typechain-0.1.1.tgz", + "integrity": "sha512-UXS6m0MUzomDWFfd6Jivbz/wmNZo4dpW/Qa6Lq89qhS/qms/j1haJqlMxsDu+tCi8i/JH/IZtFkiEmEQ1PgmhA==", + "dev": true + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "dev": true, + "dependencies": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", + "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.0" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "node_modules/caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "dev": true, + "dependencies": { + "get-proxy": "^2.0.0", + "isurl": "^1.0.0-alpha5", + "tunnel-agent": "^0.6.0", + "url-to-options": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cbor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-5.1.0.tgz", + "integrity": "sha512-qzEc7kUShdMbWTaUH7X+aHW8owvBU3FS0dfYR1lGYpoZr0mGJhhojLlZJH653x/DfeMZ56h315FRNBUIG1R7qg==", + "dev": true, + "dependencies": { + "bignumber.js": "^9.0.0", + "nofilter": "^1.0.4" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai-bignumber": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chai-bignumber/-/chai-bignumber-3.0.0.tgz", + "integrity": "sha512-SubOtaSI2AILWTWe2j0c6i2yFT/f9J6UBjeVGDuwDiPLkF/U5+/eTWUE3sbCZ1KgcPF6UJsDVYbIxaYA097MQA==", + "dev": true + }, + "node_modules/chai-bn": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/chai-bn/-/chai-bn-0.2.1.tgz", + "integrity": "sha512-01jt2gSXAw7UYFPT5K8d7HYjdXj2vyeIuE+0T/34FWzlNcVbs1JkPxRu7rYMfQnJhrHT8Nr6qjSf5ZwwLU2EYg==", + "dev": true + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/checkpoint-store": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz", + "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", + "dev": true, + "dependencies": { + "functional-red-black-tree": "^1.0.1" + } + }, + "node_modules/chokidar": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.1.2" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", + "dev": true, + "dependencies": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "dev": true + }, + "node_modules/command-line-args": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-4.0.7.tgz", + "integrity": "sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "find-replace": "^1.0.3", + "typical": "^2.6.1" + }, + "bin": { + "command-line-args": "bin/cli.js" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "node_modules/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "dev": true + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/core-js-pure": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.7.0.tgz", + "integrity": "sha512-EZD2ckZysv8MMt4J6HSvS9K2GdtlZtdBncKAmF9lr2n0c9dJUaUN88PSTjvgwCgQPWKTkERXITgS6JJRAnljtg==", + "dev": true, + "hasInstallScript": true + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/parse-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cosmiconfig/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/cross-spawn/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/death": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", + "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=", + "dev": true + }, + "node_modules/debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "dev": true, + "dependencies": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "dev": true, + "dependencies": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tar/node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "dev": true, + "dependencies": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2/node_modules/file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "dev": true, + "dependencies": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-targz/node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "dev": true, + "dependencies": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip/node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-unzip/node_modules/get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "dev": true, + "dependencies": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-unzip/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "node_modules/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "node_modules/deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.6.0" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-properties/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "node_modules/detect-port": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", + "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", + "dev": true, + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-to-object": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-to-object/-/dir-to-object-2.0.0.tgz", + "integrity": "sha512-sXs0JKIhymON7T1UZuO2Ud6VTNAx/VTBXIl4+3mjb2RgfOpt+hectX0x04YqPOPdkeOAKoJuKqwqnXXURNPNEA==", + "dev": true + }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", + "dev": true + }, + "node_modules/dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/download": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", + "integrity": "sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==", + "dev": true, + "dependencies": { + "archive-type": "^4.0.0", + "caw": "^2.0.1", + "content-disposition": "^0.5.2", + "decompress": "^4.2.0", + "ext-name": "^5.0.0", + "file-type": "^8.1.0", + "filenamify": "^2.0.0", + "get-stream": "^3.0.0", + "got": "^8.3.1", + "make-dir": "^1.2.0", + "p-event": "^2.1.0", + "pify": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "node_modules/elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding-down": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", + "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", + "dev": true, + "dependencies": { + "abstract-leveldown": "^5.0.0", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0", + "xtend": "^4.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/encoding-down/node_modules/abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/encoding-down/node_modules/level-codec": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", + "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", + "dev": true, + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/encoding-down/node_modules/level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/encoding-down/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/env-paths": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", + "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-abstract/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "dependencies": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "dependencies": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=0.12.0" + }, + "optionalDependencies": { + "source-map": "~0.2.0" + } + }, + "node_modules/escodegen/node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.7.0.tgz", + "integrity": "sha512-CStQYJgALoQBw3FsBzH0VOVDRnJ/ZimUlpLm226U8qgqYJfPOY/CPK6wyRInMxh73HSKg5wyRwdS4BVYYHwokA==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.1", + "jest-docblock": "^21.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima-extract-comments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz", + "integrity": "sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eth-ens-namehash": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", + "integrity": "sha1-IprEbsqG1S4MmR58sq74P/D2i88=", + "dev": true, + "dependencies": { + "idna-uts46-hx": "^2.3.1", + "js-sha3": "^0.5.7" + } + }, + "node_modules/eth-ens-namehash/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/eth-gas-reporter": { + "version": "0.2.19", + "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.19.tgz", + "integrity": "sha512-yQmbAa6O9/Yl/syNml2A0R+ZLQnJ9m9jogFXHzjMWVBMUVnAcEskOVyxaMYddkclZdYIMxE99tQy830C2jLsAQ==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.0.0-beta.146", + "@solidity-parser/parser": "^0.8.0", + "cli-table3": "^0.5.0", + "colors": "^1.1.2", + "ethereumjs-util": "6.2.0", + "ethers": "^4.0.40", + "fs-readdir-recursive": "^1.1.0", + "lodash": "^4.17.14", + "markdown-table": "^1.1.3", + "mocha": "^7.1.1", + "req-cwd": "^2.0.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.5", + "sha1": "^1.1.1", + "sync-request": "^6.0.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/@solidity-parser/parser": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.8.2.tgz", + "integrity": "sha512-8LySx3qrNXPgB5JiULfG10O3V7QTxI/TLzSw5hFQhXWSkVxZBAv4rZQ0sYgLEbc8g3L2lmnujj1hKul38Eu5NQ==", + "dev": true + }, + "node_modules/eth-gas-reporter/node_modules/ethereumjs-util": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz", + "integrity": "sha512-vb0XN9J2QGdZGIEKG2vXM+kUdEivUfU6Wmi5y0cg+LRhDYKnXIZ/Lz7XjFbHRR9VIKq2lVGLzGBkA++y2nOdOQ==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^2.0.0", + "rlp": "^2.2.3", + "secp256k1": "^3.0.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/ethers": { + "version": "4.0.48", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.48.tgz", + "integrity": "sha512-sZD5K8H28dOrcidzx9f8KYh8083n5BexIO3+SbE4jK83L85FxtpXZBCQdXb8gkg+7sBqomcLhhkU7UHL+F7I2g==", + "dev": true, + "dependencies": { + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "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" + } + }, + "node_modules/eth-gas-reporter/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/eth-gas-reporter/node_modules/keccak": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", + "integrity": "sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "inherits": "^2.0.4", + "nan": "^2.14.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=5.12.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/scrypt-js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", + "dev": true + }, + "node_modules/eth-gas-reporter/node_modules/secp256k1": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz", + "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "bip66": "^1.1.5", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "drbg.js": "^1.0.1", + "elliptic": "^6.5.2", + "nan": "^2.14.0", + "safe-buffer": "^5.1.2" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", + "dev": true + }, + "node_modules/eth-gas-reporter/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", + "dev": true + }, + "node_modules/eth-lib": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/eth-sig-util": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.5.3.tgz", + "integrity": "sha512-KpXbCKmmBUNUTGh9MRKmNkIPietfhzBqqYqysDavLseIiMUGl95k6UcPEkALAZlj41e9E6yioYXc1PC333RKqw==", + "dev": true, + "dependencies": { + "buffer": "^5.2.1", + "elliptic": "^6.4.0", + "ethereumjs-abi": "0.6.5", + "ethereumjs-util": "^5.1.1", + "tweetnacl": "^1.0.0", + "tweetnacl-util": "^0.15.0" + } + }, + "node_modules/eth-sig-util/node_modules/ethereumjs-abi": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz", + "integrity": "sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=", + "dev": true, + "dependencies": { + "bn.js": "^4.10.0", + "ethereumjs-util": "^4.3.0" + } + }, + "node_modules/eth-sig-util/node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz", + "integrity": "sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w==", + "dev": true, + "dependencies": { + "bn.js": "^4.8.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.0.0" + } + }, + "node_modules/eth-sig-util/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ethashjs": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ethashjs/-/ethashjs-0.0.8.tgz", + "integrity": "sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "buffer-xor": "^2.0.1", + "ethereumjs-util": "^7.0.2", + "miller-rabin": "^4.0.0" + } + }, + "node_modules/ethashjs/node_modules/buffer-xor": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", + "integrity": "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ethereum-bloom-filters": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.7.tgz", + "integrity": "sha512-cDcJJSJ9GMAcURiAWO3DxIEhTL/uWqlQnvgKpuYQzYPrt/izuGU+1ntQmHt0IRq6ADoSYHFnB+aCEFIldjhkMQ==", + "dev": true, + "dependencies": { + "js-sha3": "^0.8.0" + } + }, + "node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/ethereum-waffle": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/ethereum-waffle/-/ethereum-waffle-3.0.2.tgz", + "integrity": "sha512-VJQTL9oBbHIQRxQFuh1NBXoFXSlTIY6DrkPpO7CvevXRI9ixxq01nSc6hPYUIVy7s+U03sp4ply497O6mD3gsQ==", + "dev": true, + "dependencies": { + "@ethereum-waffle/chai": "^3.0.2", + "@ethereum-waffle/compiler": "^3.0.2", + "@ethereum-waffle/mock-contract": "^3.0.2", + "@ethereum-waffle/provider": "^3.0.2", + "ethers": "^5.0.1" + }, + "bin": { + "waffle": "bin/waffle" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/ethereumjs-abi": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", + "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ethereumjs-account": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz", + "integrity": "sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA==", + "dev": true, + "dependencies": { + "ethereumjs-util": "^6.0.0", + "rlp": "^2.2.1", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ethereumjs-account/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ethereumjs-block": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", + "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ethereumjs-block/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ethereumjs-block/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/ethereumjs-block/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ethereumjs-block/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/ethereumjs-block/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/ethereumjs-block/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ethereumjs-block/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/ethereumjs-block/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ethereumjs-blockchain": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz", + "integrity": "sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ==", + "dev": true, + "dependencies": { + "async": "^2.6.1", + "ethashjs": "~0.0.7", + "ethereumjs-block": "~2.2.2", + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.1.0", + "flow-stoplight": "^1.0.0", + "level-mem": "^3.0.1", + "lru-cache": "^5.1.1", + "rlp": "^2.2.2", + "semaphore": "^1.1.0" + } + }, + "node_modules/ethereumjs-blockchain/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ethereumjs-common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz", + "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==", + "dev": true + }, + "node_modules/ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "dev": true, + "dependencies": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ethereumjs-tx/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ethereumjs-util": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.2.tgz", + "integrity": "sha512-ATAP02eJLpAlWGfiKQddNrRfZpwXiTFhRN2EM/yLXMCdBW/xjKYblNKcx8GLzzrjXg0ymotck+lam1nuV90arQ==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^3.0.0", + "rlp": "^2.2.4", + "secp256k1": "^4.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ethereumjs-util/node_modules/bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "node_modules/ethers": { + "version": "5.0.19", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.0.19.tgz", + "integrity": "sha512-0AZnUgZh98q888WAd1oI3aLeI+iyDtrupjANVtPPS7O63lVopkR/No8A1NqSkgl/rU+b2iuu2mUZor6GD4RG2w==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "5.0.7", + "@ethersproject/abstract-provider": "5.0.5", + "@ethersproject/abstract-signer": "5.0.7", + "@ethersproject/address": "5.0.5", + "@ethersproject/base64": "5.0.4", + "@ethersproject/basex": "5.0.4", + "@ethersproject/bignumber": "5.0.8", + "@ethersproject/bytes": "5.0.5", + "@ethersproject/constants": "5.0.5", + "@ethersproject/contracts": "5.0.5", + "@ethersproject/hash": "5.0.6", + "@ethersproject/hdnode": "5.0.5", + "@ethersproject/json-wallets": "5.0.7", + "@ethersproject/keccak256": "5.0.4", + "@ethersproject/logger": "5.0.6", + "@ethersproject/networks": "5.0.4", + "@ethersproject/pbkdf2": "5.0.4", + "@ethersproject/properties": "5.0.4", + "@ethersproject/providers": "5.0.14", + "@ethersproject/random": "5.0.4", + "@ethersproject/rlp": "5.0.4", + "@ethersproject/sha2": "5.0.4", + "@ethersproject/signing-key": "5.0.5", + "@ethersproject/solidity": "5.0.5", + "@ethersproject/strings": "5.0.5", + "@ethersproject/transactions": "5.0.6", + "@ethersproject/units": "5.0.6", + "@ethersproject/wallet": "5.0.7", + "@ethersproject/web": "5.0.9", + "@ethersproject/wordlists": "5.0.5" + } + }, + "node_modules/ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", + "dev": true, + "dependencies": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ethjs-unit/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true + }, + "node_modules/ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dev": true, + "dependencies": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "dev": true + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/execa": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz", + "integrity": "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^3.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": "^8.12.0 || >=9.7.0" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/express/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "dependencies": { + "type": "^2.0.0" + } + }, + "node_modules/ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "dev": true, + "dependencies": { + "mime-db": "^1.28.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "dev": true, + "dependencies": { + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extract-comments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/extract-comments/-/extract-comments-1.1.0.tgz", + "integrity": "sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q==", + "dev": true, + "dependencies": { + "esprima-extract-comments": "^1.1.0", + "parse-code-context": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fake-merkle-patricia-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz", + "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", + "dev": true, + "dependencies": { + "checkpoint-store": "^1.1.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fast-glob/node_modules/micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/fastq": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz", + "integrity": "sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-type": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", + "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", + "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", + "dev": true, + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/find-replace": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-1.0.3.tgz", + "integrity": "sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A=", + "dev": true, + "dependencies": { + "array-back": "^1.0.4", + "test-value": "^2.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-replace/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/find-versions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", + "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "dev": true, + "dependencies": { + "semver-regex": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-yarn-workspace-root": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz", + "integrity": "sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==", + "dev": true, + "dependencies": { + "fs-extra": "^4.0.3", + "micromatch": "^3.1.4" + } + }, + "node_modules/find-yarn-workspace-root/node_modules/fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "dev": true, + "dependencies": { + "is-buffer": "~2.0.3" + }, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flow-stoplight": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz", + "integrity": "sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s=", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fp-ts": { + "version": "1.19.3", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", + "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", + "dev": true + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/from2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/from2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/from2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/from2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/ganache-cli": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.9.0.tgz", + "integrity": "sha512-ZdL6kPrApXF/O+f6uU431OJcwxMk69H3KPDSHHrMP82ZvZRNpDHbR+rVv7XX/YUeoQ5q6nZ2AFiGiFAVn9pfzA==", + "dev": true, + "dependencies": { + "ethereumjs-util": "6.1.0", + "source-map-support": "0.5.12", + "yargs": "13.2.4" + }, + "bin": { + "ganache-cli": "cli.js" + } + }, + "node_modules/ganache-cli/node_modules/ansi-regex": { + "version": "4.1.0", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/ansi-styles": { + "version": "3.2.1", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/bindings": { + "version": "1.5.0", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/ganache-cli/node_modules/bip66": { + "version": "1.1.5", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ganache-cli/node_modules/bn.js": { + "version": "4.11.8", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/brorand": { + "version": "1.1.0", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/browserify-aes": { + "version": "1.2.0", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ganache-cli/node_modules/buffer-from": { + "version": "1.1.1", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/buffer-xor": { + "version": "1.0.3", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/camelcase": { + "version": "5.3.1", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/cipher-base": { + "version": "1.0.4", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ganache-cli/node_modules/cliui": { + "version": "5.0.0", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/ganache-cli/node_modules/color-convert": { + "version": "1.9.3", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ganache-cli/node_modules/color-name": { + "version": "1.1.3", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/create-hash": { + "version": "1.2.0", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/ganache-cli/node_modules/create-hmac": { + "version": "1.1.7", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/ganache-cli/node_modules/cross-spawn": { + "version": "6.0.5", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/ganache-cli/node_modules/decamelize": { + "version": "1.2.0", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/drbg.js": { + "version": "1.0.1", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/ganache-cli/node_modules/elliptic": { + "version": "6.5.0", + "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/ganache-cli/node_modules/emoji-regex": { + "version": "7.0.3", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/end-of-stream": { + "version": "1.4.1", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/ganache-cli/node_modules/ethereumjs-util": { + "version": "6.1.0", + "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + }, + "node_modules/ganache-cli/node_modules/ethjs-util": { + "version": "0.1.6", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dev": true, + "dependencies": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-cli/node_modules/evp_bytestokey": { + "version": "1.0.3", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-cli/node_modules/execa": { + "version": "1.0.0", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/file-uri-to-path": { + "version": "1.0.0", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/find-up": { + "version": "3.0.0", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/get-caller-file": { + "version": "2.0.5", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/ganache-cli/node_modules/get-stream": { + "version": "4.1.0", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/hash-base": { + "version": "3.0.4", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/hash.js": { + "version": "1.1.7", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/ganache-cli/node_modules/hmac-drbg": { + "version": "1.0.1", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/ganache-cli/node_modules/inherits": { + "version": "2.0.4", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/invert-kv": { + "version": "2.0.0", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/is-hex-prefixed": { + "version": "1.0.0", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", + "dev": true, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-cli/node_modules/is-stream": { + "version": "1.1.0", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/isexe": { + "version": "2.0.0", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/keccak": { + "version": "1.4.0", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.2.1", + "inherits": "^2.0.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/ganache-cli/node_modules/lcid": { + "version": "2.0.0", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "dependencies": { + "invert-kv": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/locate-path": { + "version": "3.0.0", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/map-age-cleaner": { + "version": "0.1.3", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/md5.js": { + "version": "1.3.5", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/ganache-cli/node_modules/mem": { + "version": "4.3.0", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "dependencies": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/mimic-fn": { + "version": "2.1.0", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/minimalistic-assert": { + "version": "1.0.1", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/nan": { + "version": "2.14.0", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/nice-try": { + "version": "1.0.5", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/npm-run-path": { + "version": "2.0.2", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/once": { + "version": "1.4.0", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ganache-cli/node_modules/os-locale": { + "version": "3.1.0", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "dependencies": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/p-defer": { + "version": "1.0.0", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/p-finally": { + "version": "1.0.0", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/p-is-promise": { + "version": "2.1.0", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/p-limit": { + "version": "2.2.0", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/p-locate": { + "version": "3.0.0", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/p-try": { + "version": "2.2.0", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/path-exists": { + "version": "3.0.0", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/path-key": { + "version": "2.0.1", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/pump": { + "version": "3.0.0", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/ganache-cli/node_modules/require-directory": { + "version": "2.1.1", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/require-main-filename": { + "version": "2.0.0", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/ripemd160": { + "version": "2.0.2", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/ganache-cli/node_modules/rlp": { + "version": "2.2.3", + "integrity": "sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.1", + "safe-buffer": "^5.1.1" + }, + "bin": { + "rlp": "bin/rlp" + } + }, + "node_modules/ganache-cli/node_modules/safe-buffer": { + "version": "5.2.0", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/secp256k1": { + "version": "3.7.1", + "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "bip66": "^1.1.5", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "drbg.js": "^1.0.1", + "elliptic": "^6.4.1", + "nan": "^2.14.0", + "safe-buffer": "^5.1.2" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/ganache-cli/node_modules/semver": { + "version": "5.7.0", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-cli/node_modules/set-blocking": { + "version": "2.0.0", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/sha.js": { + "version": "2.4.11", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/ganache-cli/node_modules/shebang-command": { + "version": "1.2.0", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/shebang-regex": { + "version": "1.0.0", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/signal-exit": { + "version": "3.0.2", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/source-map": { + "version": "0.6.1", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/source-map-support": { + "version": "0.5.12", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/ganache-cli/node_modules/string-width": { + "version": "3.1.0", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/strip-ansi": { + "version": "5.2.0", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/strip-eof": { + "version": "1.0.0", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/strip-hex-prefix": { + "version": "1.0.0", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "dev": true, + "dependencies": { + "is-hex-prefixed": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-cli/node_modules/which": { + "version": "1.3.1", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/ganache-cli/node_modules/which-module": { + "version": "2.0.0", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/wrap-ansi": { + "version": "5.1.0", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/wrappy": { + "version": "1.0.2", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/y18n": { + "version": "4.0.0", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/yargs": { + "version": "13.2.4", + "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.0" + } + }, + "node_modules/ganache-cli/node_modules/yargs-parser": { + "version": "13.1.1", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/ganache-core": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/ganache-core/-/ganache-core-2.13.1.tgz", + "integrity": "sha512-Ewg+kNcDqXtOohe7jCcP+ZUv9EMzOx2MoqOYYP3BCfxrDh3KjBXXaKK+Let7li0TghAs9lxmBgevZku35j5YzA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "3.0.0", + "async": "2.6.2", + "bip39": "2.5.0", + "cachedown": "1.0.0", + "clone": "2.1.2", + "debug": "3.2.6", + "encoding-down": "5.0.4", + "eth-sig-util": "^2.0.0", + "ethereumjs-abi": "0.6.8", + "ethereumjs-account": "3.0.0", + "ethereumjs-block": "2.2.2", + "ethereumjs-common": "1.5.0", + "ethereumjs-tx": "2.1.2", + "ethereumjs-util": "6.2.1", + "ethereumjs-vm": "4.2.0", + "heap": "0.2.6", + "keccak": "3.0.1", + "level-sublevel": "6.6.4", + "levelup": "3.1.1", + "lodash": "4.17.20", + "lru-cache": "5.1.1", + "merkle-patricia-tree": "3.0.0", + "patch-package": "6.2.2", + "seedrandom": "3.0.1", + "source-map-support": "0.5.12", + "tmp": "0.1.0", + "web3-provider-engine": "14.2.1", + "websocket": "1.0.32" + }, + "engines": { + "node": ">=8.9.0" + }, + "optionalDependencies": { + "ethereumjs-wallet": "0.6.5", + "web3": "1.2.11" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/abi": { + "version": "5.0.0-beta.153", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz", + "integrity": "sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/address": ">=5.0.0-beta.128", + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/constants": ">=5.0.0-beta.128", + "@ethersproject/hash": ">=5.0.0-beta.128", + "@ethersproject/keccak256": ">=5.0.0-beta.127", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/strings": ">=5.0.0-beta.130" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/address": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.5.tgz", + "integrity": "sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/rlp": "^5.0.3", + "bn.js": "^4.4.0" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/bignumber": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.8.tgz", + "integrity": "sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "bn.js": "^4.4.0" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/bytes": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.5.tgz", + "integrity": "sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/constants": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.5.tgz", + "integrity": "sha512-foaQVmxp2+ik9FrLUCtVrLZCj4M3Ibgkqvh+Xw/vFRSerkjVSYePApaVE5essxhoSlF1U9oXfWY09QI2AXtgKA==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/hash": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.5.tgz", + "integrity": "sha512-GpI80/h2HDpfNKpCZoxQJCjOQloGnlD5hM1G+tZe8FQDJhEvFjJoPDuWv+NaYjJfOciKS2Axqc4Q4WamdLoUgg==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/keccak256": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.4.tgz", + "integrity": "sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "js-sha3": "0.5.7" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/logger": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.6.tgz", + "integrity": "sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/@ethersproject/properties": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.4.tgz", + "integrity": "sha512-UdyX3GqBxFt15B0uSESdDNmhvEbK3ACdDXl2soshoPcneXuTswHDeA0LoPlnaZzhbgk4p6jqb4GMms5C26Qu6A==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/rlp": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.4.tgz", + "integrity": "sha512-5qrrZad7VTjofxSsm7Zg/7Dr4ZOln4S2CqiDdOuTv6MBKnXj0CiBojXyuDy52M8O3wxH0CyE924hXWTDV1PQWQ==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/signing-key": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.5.tgz", + "integrity": "sha512-Z1wY7JC1HVO4CvQWY2TyTTuAr8xK3bJijZw1a9G92JEmKdv1j255R/0YLBBcFTl2J65LUjtXynNJ2GbArPGi5g==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "elliptic": "6.5.3" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/strings": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.5.tgz", + "integrity": "sha512-JED6WaIV00xM/gvj8vSnd+0VWtDYdidTmavFRCTQakqfz+4tDo6Jz5LHgG+dd45h7ah7ykCHW0C7ZXWEDROCXQ==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/transactions": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.6.tgz", + "integrity": "sha512-htsFhOD+NMBxx676A8ehSuwVV49iqpSB+CkjPZ02tpNew0K6p8g0CZ46Z1ZP946gIHAU80xQ0NACHYrjIUaCFA==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/rlp": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4" + } + }, + "node_modules/ganache-core/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "optional": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ganache-core/node_modules/@types/node": { + "version": "14.11.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.8.tgz", + "integrity": "sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/@types/pbkdf2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", + "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ganache-core/node_modules/@types/secp256k1": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", + "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ganache-core/node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/abstract-leveldown": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz", + "integrity": "sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "optional": true, + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/aes-js": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", + "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ajv": { + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/ganache-core/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/ganache-core/node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ganache-core/node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ganache-core/node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.11" + } + }, + "node_modules/ganache-core/node_modules/async-eventemitter": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", + "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", + "dev": true, + "dependencies": { + "async": "^2.4.0" + } + }, + "node_modules/ganache-core/node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/ganache-core/node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/ganache-core/node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/aws4": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "dependencies": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ganache-core/node_modules/babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "dependencies": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + } + }, + "node_modules/ganache-core/node_modules/babel-core/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/babel-core/node_modules/json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/ganache-core/node_modules/babel-core/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-core/node_modules/slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "dependencies": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/babel-generator/node_modules/jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "dependencies": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "dependencies": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "dependencies": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "dependencies": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "dependencies": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "dependencies": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "dependencies": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "dependencies": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "dependencies": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "dependencies": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "dev": true, + "dependencies": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "dependencies": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "dependencies": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "dependencies": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "dependencies": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "dependencies": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "dependencies": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "dependencies": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "dependencies": { + "regenerator-transform": "^0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true, + "dependencies": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + } + }, + "node_modules/ganache-core/node_modules/babel-preset-env/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "dependencies": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + } + }, + "node_modules/ganache-core/node_modules/babel-register/node_modules/source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/ganache-core/node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/ganache-core/node_modules/babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "node_modules/ganache-core/node_modules/babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "dependencies": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "node_modules/ganache-core/node_modules/babel-traverse/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/babel-traverse/node_modules/globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-traverse/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "node_modules/ganache-core/node_modules/babel-types/node_modules/to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babelify": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", + "dev": true, + "dependencies": { + "babel-core": "^6.0.14", + "object-assign": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true, + "bin": { + "babylon": "bin/babylon.js" + } + }, + "node_modules/ganache-core/node_modules/backoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", + "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", + "dev": true, + "dependencies": { + "precond": "0.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "node_modules/ganache-core/node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/base-x": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", + "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ganache-core/node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/ganache-core/node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/ganache-core/node_modules/bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", + "dev": true, + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/bip39": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-2.5.0.tgz", + "integrity": "sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.0", + "pbkdf2": "^3.0.9", + "randombytes": "^2.0.1", + "safe-buffer": "^5.0.1", + "unorm": "^1.3.3" + } + }, + "node_modules/ganache-core/node_modules/blakejs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", + "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=", + "dev": true + }, + "node_modules/ganache-core/node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "optional": true, + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/body-parser/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ganache-core/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/ganache-core/node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ganache-core/node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "optional": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "optional": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/ganache-core/node_modules/browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/ganache-core/node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/ganache-core/node_modules/browserify-sign/node_modules/bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/browserify-sign/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ganache-core/node_modules/browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + }, + "bin": { + "browserslist": "cli.js" + } + }, + "node_modules/ganache-core/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "dev": true, + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/ganache-core/node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/ganache-core/node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dev": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/ganache-core/node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/ganache-core/node_modules/buffer-to-arraybuffer": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", + "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "node_modules/ganache-core/node_modules/bufferutil": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", + "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "~3.7.0" + } + }, + "node_modules/ganache-core/node_modules/bufferutil/node_modules/node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/ganache-core/node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/bytewise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", + "integrity": "sha1-HRPL/3F65xWAlKqIGzXQgbOHJT4=", + "dev": true, + "dependencies": { + "bytewise-core": "^1.2.2", + "typewise": "^1.0.3" + } + }, + "node_modules/ganache-core/node_modules/bytewise-core": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz", + "integrity": "sha1-P7QQx+kVWOsasiqCg0V3qmvWHUI=", + "dev": true, + "dependencies": { + "typewise-core": "^1.2" + } + }, + "node_modules/ganache-core/node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "optional": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ganache-core/node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ganache-core/node_modules/cachedown": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cachedown/-/cachedown-1.0.0.tgz", + "integrity": "sha1-1D8DbkUQaWsxJG19sx6/D3rDLRU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "^2.4.1", + "lru-cache": "^3.2.0" + } + }, + "node_modules/ganache-core/node_modules/cachedown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/cachedown/node_modules/lru-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", + "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/caniuse-lite": { + "version": "1.0.30001146", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001146.tgz", + "integrity": "sha512-VAy5RHDfTJhpxnDdp2n40GPPLp3KqNrXz1QqFv4J64HvArKs8nuNMOWkB3ICOaBTU/Aj4rYAo/ytdQDDFF/Pug==", + "dev": true + }, + "node_modules/ganache-core/node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "node_modules/ganache-core/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/checkpoint-store": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz", + "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", + "dev": true, + "dependencies": { + "functional-red-black-tree": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/cids": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", + "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", + "dev": true, + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "class-is": "^1.1.0", + "multibase": "~0.6.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.15" + }, + "engines": { + "node": ">=4.0.0", + "npm": ">=3.0.0" + } + }, + "node_modules/ganache-core/node_modules/cids/node_modules/multicodec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", + "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", + "dev": true, + "optional": true, + "dependencies": { + "buffer": "^5.6.0", + "varint": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ganache-core/node_modules/class-is": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", + "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ganache-core/node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "optional": true, + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ganache-core/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/ganache-core/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/ganache-core/node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "optional": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/content-hash": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", + "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", + "dev": true, + "optional": true, + "dependencies": { + "cids": "^0.7.1", + "multicodec": "^0.5.5", + "multihashes": "^0.4.15" + } + }, + "node_modules/ganache-core/node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/ganache-core/node_modules/convert-source-map/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true, + "hasInstallScript": true + }, + "node_modules/ganache-core/node_modules/core-js-pure": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", + "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==", + "dev": true, + "hasInstallScript": true + }, + "node_modules/ganache-core/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/ganache-core/node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "optional": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ganache-core/node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/ganache-core/node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/ganache-core/node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/ganache-core/node_modules/cross-fetch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.3.tgz", + "integrity": "sha512-PrWWNH3yL2NYIb/7WF/5vFG3DCQiXDOVf8k3ijatbrtnwNuhMWLC7YF7uqf53tbTFDzHIUD8oITw4Bxt8ST3Nw==", + "dev": true, + "dependencies": { + "node-fetch": "2.1.2", + "whatwg-fetch": "2.0.4" + } + }, + "node_modules/ganache-core/node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "optional": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/ganache-core/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/ganache-core/node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/ganache-core/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "optional": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "dependencies": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "node_modules/ganache-core/node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/deferred-leveldown": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", + "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~5.0.0", + "inherits": "^2.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/deferred-leveldown/node_modules/abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ganache-core/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "optional": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "dependencies": { + "repeating": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/ganache-core/node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/dotignore": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz", + "integrity": "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.4" + }, + "bin": { + "ignored": "bin/ignored" + } + }, + "node_modules/ganache-core/node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ganache-core/node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/electron-to-chromium": { + "version": "1.3.578", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.578.tgz", + "integrity": "sha512-z4gU6dA1CbBJsAErW5swTGAaU2TBzc2mPAonJb00zqW1rOraDo2zfBMDRvaz9cVic+0JEZiYbHWPw/fTaZlG2Q==", + "dev": true + }, + "node_modules/ganache-core/node_modules/elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/ganache-core/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/ganache-core/node_modules/encoding-down": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", + "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", + "dev": true, + "dependencies": { + "abstract-leveldown": "^5.0.0", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0", + "xtend": "^4.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/encoding-down/node_modules/abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/ganache-core/node_modules/errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/ganache-core/node_modules/es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "dependencies": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "node_modules/ganache-core/node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/ganache-core/node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/ganache-core/node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ganache-core/node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/eth-block-tracker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz", + "integrity": "sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug==", + "dev": true, + "dependencies": { + "eth-query": "^2.1.0", + "ethereumjs-tx": "^1.3.3", + "ethereumjs-util": "^5.1.3", + "ethjs-util": "^0.1.3", + "json-rpc-engine": "^3.6.0", + "pify": "^2.3.0", + "tape": "^4.6.3" + } + }, + "node_modules/ganache-core/node_modules/eth-block-tracker/node_modules/ethereumjs-tx": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", + "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", + "dev": true, + "dependencies": { + "ethereum-common": "^0.0.18", + "ethereumjs-util": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-block-tracker/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-block-tracker/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/eth-ens-namehash": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", + "integrity": "sha1-IprEbsqG1S4MmR58sq74P/D2i88=", + "dev": true, + "optional": true, + "dependencies": { + "idna-uts46-hx": "^2.3.1", + "js-sha3": "^0.5.7" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-infura": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz", + "integrity": "sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw==", + "dev": true, + "dependencies": { + "cross-fetch": "^2.1.1", + "eth-json-rpc-middleware": "^1.5.0", + "json-rpc-engine": "^3.4.0", + "json-rpc-error": "^2.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz", + "integrity": "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==", + "dev": true, + "dependencies": { + "async": "^2.5.0", + "eth-query": "^2.1.2", + "eth-tx-summary": "^3.1.2", + "ethereumjs-block": "^1.6.0", + "ethereumjs-tx": "^1.3.3", + "ethereumjs-util": "^5.1.2", + "ethereumjs-vm": "^2.1.0", + "fetch-ponyfill": "^4.0.0", + "json-rpc-engine": "^3.6.0", + "json-rpc-error": "^2.0.0", + "json-stable-stringify": "^1.0.1", + "promise-to-callback": "^1.0.0", + "tape": "^4.6.3" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.6.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-account": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", + "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", + "dev": true, + "dependencies": { + "ethereumjs-util": "^5.0.0", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-block": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "^1.2.2", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-block/node_modules/ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-tx": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", + "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", + "dev": true, + "dependencies": { + "ethereum-common": "^0.0.18", + "ethereumjs-util": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz", + "integrity": "sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "async-eventemitter": "^0.2.2", + "ethereumjs-account": "^2.0.3", + "ethereumjs-block": "~2.2.0", + "ethereumjs-common": "^1.1.0", + "ethereumjs-util": "^6.0.0", + "fake-merkle-patricia-tree": "^1.0.1", + "functional-red-black-tree": "^1.0.1", + "merkle-patricia-tree": "^2.3.2", + "rustbn.js": "~0.2.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm/node_modules/ethereumjs-block": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", + "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm/node_modules/ethereumjs-block/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm/node_modules/ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "dev": true, + "dependencies": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-ws/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-ws/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-lib": { + "version": "0.1.29", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz", + "integrity": "sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "nano-json-stream-parser": "^0.1.2", + "servify": "^0.1.12", + "ws": "^3.0.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/ganache-core/node_modules/eth-query": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz", + "integrity": "sha1-1nQdkAAQa1FRDHLbktY2VFam2l4=", + "dev": true, + "dependencies": { + "json-rpc-random-id": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "node_modules/ganache-core/node_modules/eth-sig-util": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.3.0.tgz", + "integrity": "sha512-ugD1AvaggvKaZDgnS19W5qOfepjGc7qHrt7TrAaL54gJw9SHvgIXJ3r2xOMW30RWJZNP+1GlTOy5oye7yXA4xA==", + "dev": true, + "dependencies": { + "buffer": "^5.2.1", + "elliptic": "^6.4.0", + "ethereumjs-abi": "0.6.5", + "ethereumjs-util": "^5.1.1", + "tweetnacl": "^1.0.0", + "tweetnacl-util": "^0.15.0" + } + }, + "node_modules/ganache-core/node_modules/eth-sig-util/node_modules/ethereumjs-abi": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz", + "integrity": "sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=", + "dev": true, + "dependencies": { + "bn.js": "^4.10.0", + "ethereumjs-util": "^4.3.0" + } + }, + "node_modules/ganache-core/node_modules/eth-sig-util/node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz", + "integrity": "sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w==", + "dev": true, + "dependencies": { + "bn.js": "^4.8.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-sig-util/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz", + "integrity": "sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "clone": "^2.0.0", + "concat-stream": "^1.5.1", + "end-of-stream": "^1.1.0", + "eth-query": "^2.0.2", + "ethereumjs-block": "^1.4.1", + "ethereumjs-tx": "^1.1.1", + "ethereumjs-util": "^5.0.1", + "ethereumjs-vm": "^2.6.0", + "through2": "^2.0.3" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.6.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-account": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", + "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", + "dev": true, + "dependencies": { + "ethereumjs-util": "^5.0.0", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-block": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "^1.2.2", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-block/node_modules/ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-tx": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", + "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", + "dev": true, + "dependencies": { + "ethereum-common": "^0.0.18", + "ethereumjs-util": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz", + "integrity": "sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "async-eventemitter": "^0.2.2", + "ethereumjs-account": "^2.0.3", + "ethereumjs-block": "~2.2.0", + "ethereumjs-common": "^1.1.0", + "ethereumjs-util": "^6.0.0", + "fake-merkle-patricia-tree": "^1.0.1", + "functional-red-black-tree": "^1.0.1", + "merkle-patricia-tree": "^2.3.2", + "rustbn.js": "~0.2.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm/node_modules/ethereumjs-block": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", + "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm/node_modules/ethereumjs-block/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm/node_modules/ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "dev": true, + "dependencies": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-ws/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-ws/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethashjs": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ethashjs/-/ethashjs-0.0.8.tgz", + "integrity": "sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "buffer-xor": "^2.0.1", + "ethereumjs-util": "^7.0.2", + "miller-rabin": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethashjs/node_modules/bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethashjs/node_modules/buffer-xor": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", + "integrity": "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethashjs/node_modules/ethereumjs-util": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.6.tgz", + "integrity": "sha512-E9aJ9W7XZkcBqIblfstBU+0nGSjF9Dz/Ps7s1NTFOgDZM8pwD+nX1P1GBJeSqB6Osxhj2UtuxVCqjvmrj2svzw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereum-bloom-filters": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.7.tgz", + "integrity": "sha512-cDcJJSJ9GMAcURiAWO3DxIEhTL/uWqlQnvgKpuYQzYPrt/izuGU+1ntQmHt0IRq6ADoSYHFnB+aCEFIldjhkMQ==", + "dev": true, + "optional": true, + "dependencies": { + "js-sha3": "^0.8.0" + } + }, + "node_modules/ganache-core/node_modules/ethereum-bloom-filters/node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ethereum-common": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", + "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-abi": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", + "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-account": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz", + "integrity": "sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA==", + "dev": true, + "dependencies": { + "ethereumjs-util": "^6.0.0", + "rlp": "^2.2.1", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", + "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.6.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-ws/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-ws/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-blockchain": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz", + "integrity": "sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ==", + "dev": true, + "dependencies": { + "async": "^2.6.1", + "ethashjs": "~0.0.7", + "ethereumjs-block": "~2.2.2", + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.1.0", + "flow-stoplight": "^1.0.0", + "level-mem": "^3.0.1", + "lru-cache": "^5.1.1", + "rlp": "^2.2.2", + "semaphore": "^1.1.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-common": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz", + "integrity": "sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "dev": true, + "dependencies": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz", + "integrity": "sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "async-eventemitter": "^0.2.2", + "core-js-pure": "^3.0.1", + "ethereumjs-account": "^3.0.0", + "ethereumjs-block": "^2.2.2", + "ethereumjs-blockchain": "^4.0.3", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.2", + "ethereumjs-util": "^6.2.0", + "fake-merkle-patricia-tree": "^1.0.1", + "functional-red-black-tree": "^1.0.1", + "merkle-patricia-tree": "^2.3.2", + "rustbn.js": "~0.2.0", + "safe-buffer": "^5.1.1", + "util.promisify": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.6.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-ws/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-ws/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-wallet": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz", + "integrity": "sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA==", + "dev": true, + "optional": true, + "dependencies": { + "aes-js": "^3.1.1", + "bs58check": "^2.1.2", + "ethereum-cryptography": "^0.1.3", + "ethereumjs-util": "^6.0.0", + "randombytes": "^2.0.6", + "safe-buffer": "^5.1.2", + "scryptsy": "^1.2.1", + "utf8": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "node_modules/ganache-core/node_modules/ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-core/node_modules/ethjs-unit/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dev": true, + "dependencies": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-core/node_modules/eventemitter3": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", + "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/ganache-core/node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/ganache-core/node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "optional": true, + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/ganache-core/node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/express/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ganache-core/node_modules/express/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "dependencies": { + "type": "^2.0.0" + } + }, + "node_modules/ganache-core/node_modules/ext/node_modules/type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/extglob/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/ganache-core/node_modules/fake-merkle-patricia-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz", + "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", + "dev": true, + "dependencies": { + "checkpoint-store": "^1.1.0" + } + }, + "node_modules/ganache-core/node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/ganache-core/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/fetch-ponyfill": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz", + "integrity": "sha1-rjzl9zLGReq4fkroeTQUcJsjmJM=", + "dev": true, + "dependencies": { + "node-fetch": "~1.7.1" + } + }, + "node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "dev": true, + "dependencies": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "optional": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz", + "integrity": "sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==", + "dev": true, + "dependencies": { + "fs-extra": "^4.0.3", + "micromatch": "^3.1.4" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/flow-stoplight": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz", + "integrity": "sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s=", + "dev": true + }, + "node_modules/ganache-core/node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/ganache-core/node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/ganache-core/node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/ganache-core/node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/ganache-core/node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/ganache-core/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "optional": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ganache-core/node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "dev": true, + "dependencies": { + "min-document": "^2.19.0", + "process": "~0.5.1" + } + }, + "node_modules/ganache-core/node_modules/global/node_modules/process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/ganache-core/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "optional": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/ganache-core/node_modules/got/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "optional": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/ganache-core/node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "dev": true, + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dev": true, + "optional": true, + "dependencies": { + "has-symbol-support-x": "^1.4.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/has-values/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/has-values/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/has-values/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ganache-core/node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/heap": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", + "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=", + "dev": true + }, + "node_modules/ganache-core/node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "optional": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/http-errors/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/http-https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", + "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/ganache-core/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/idna-uts46-hx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", + "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", + "dev": true, + "optional": true, + "dependencies": { + "punycode": "2.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/ganache-core/node_modules/idna-uts46-hx/node_modules/punycode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", + "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", + "dev": true + }, + "node_modules/ganache-core/node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/ganache-core/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ganache-core/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/ganache-core/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-fn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fn/-/is-fn-1.0.0.tgz", + "integrity": "sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", + "dev": true, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-core/node_modules/is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/ganache-core/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/ganache-core/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true, + "optional": true, + "dependencies": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ganache-core/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/json-rpc-engine": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz", + "integrity": "sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "babel-preset-env": "^1.7.0", + "babelify": "^7.3.0", + "json-rpc-error": "^2.0.0", + "promise-to-callback": "^1.0.0", + "safe-event-emitter": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/json-rpc-error": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-rpc-error/-/json-rpc-error-2.0.0.tgz", + "integrity": "sha1-p6+cICg4tekFxyUOVH8a/3cligI=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1" + } + }, + "node_modules/ganache-core/node_modules/json-rpc-random-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz", + "integrity": "sha1-uknZat7RRE27jaPSA3SKy7zeyMg=", + "dev": true + }, + "node_modules/ganache-core/node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "dependencies": { + "jsonify": "~0.0.0" + } + }, + "node_modules/ganache-core/node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/ganache-core/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/ganache-core/node_modules/jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/ganache-core/node_modules/keccak": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", + "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ganache-core/node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "optional": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/ganache-core/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, + "node_modules/ganache-core/node_modules/level-codec": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", + "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", + "dev": true, + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/level-iterator-stream": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz", + "integrity": "sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.5", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/level-mem": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-3.0.1.tgz", + "integrity": "sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg==", + "dev": true, + "dependencies": { + "level-packager": "~4.0.0", + "memdown": "~3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/level-mem/node_modules/abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/level-mem/node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/level-mem/node_modules/memdown": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz", + "integrity": "sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~5.0.0", + "functional-red-black-tree": "~1.0.1", + "immediate": "~3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/level-mem/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/level-packager": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-4.0.1.tgz", + "integrity": "sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q==", + "dev": true, + "dependencies": { + "encoding-down": "~5.0.0", + "levelup": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/level-post": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/level-post/-/level-post-1.0.7.tgz", + "integrity": "sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew==", + "dev": true, + "dependencies": { + "ltgt": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/level-sublevel": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/level-sublevel/-/level-sublevel-6.6.4.tgz", + "integrity": "sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA==", + "dev": true, + "dependencies": { + "bytewise": "~1.1.0", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0", + "level-iterator-stream": "^2.0.3", + "ltgt": "~2.1.1", + "pull-defer": "^0.2.2", + "pull-level": "^2.0.3", + "pull-stream": "^3.6.8", + "typewiselite": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/level-ws": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-1.0.0.tgz", + "integrity": "sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.2.8", + "xtend": "^4.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/levelup": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz", + "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~4.0.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~3.0.0", + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/levelup/node_modules/level-iterator-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", + "integrity": "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/looper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/looper/-/looper-2.0.0.tgz", + "integrity": "sha1-Zs0Md0rz1P7axTeU90LbVtqPCew=", + "dev": true + }, + "node_modules/ganache-core/node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/ganache-core/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/ganache-core/node_modules/ltgt": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.1.3.tgz", + "integrity": "sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ=", + "dev": true + }, + "node_modules/ganache-core/node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/ganache-core/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/merkle-patricia-tree": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz", + "integrity": "sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ==", + "dev": true, + "dependencies": { + "async": "^2.6.1", + "ethereumjs-util": "^5.2.0", + "level-mem": "^3.0.1", + "level-ws": "^1.0.0", + "readable-stream": "^3.0.6", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ganache-core/node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/merkle-patricia-tree/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ganache-core/node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/ganache-core/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "dependencies": { + "mime-db": "1.44.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "dev": true, + "dependencies": { + "dom-walk": "^0.1.0" + } + }, + "node_modules/ganache-core/node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/ganache-core/node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "optional": true, + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/ganache-core/node_modules/minizlib/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "optional": true, + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/ganache-core/node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ganache-core/node_modules/mkdirp-promise": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", + "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", + "dev": true, + "optional": true, + "dependencies": { + "mkdirp": "*" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/mock-fs": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.13.0.tgz", + "integrity": "sha512-DD0vOdofJdoaRNtnWcrXe6RQbpHkPPmtqGq14uRX0F8ZKJ5nv89CVTYl/BZdppDxBDaV0hl75htg3abpEWlPZA==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/multibase": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", + "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", + "dev": true, + "optional": true, + "dependencies": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + }, + "node_modules/ganache-core/node_modules/multicodec": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", + "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", + "dev": true, + "optional": true, + "dependencies": { + "varint": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/multihashes": { + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", + "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", + "dev": true, + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "multibase": "^0.7.0", + "varint": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/multihashes/node_modules/multibase": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", + "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", + "dev": true, + "optional": true, + "dependencies": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + }, + "node_modules/ganache-core/node_modules/nano-json-stream-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", + "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node_modules/ganache-core/node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/node-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", + "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", + "dev": true, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/ganache-core/node_modules/node-gyp-build": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/ganache-core/node_modules/normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ganache-core/node_modules/number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-core/node_modules/number-to-bn/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/object-is": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", + "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/object-is/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object.assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/object.assign/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/oboe": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.4.tgz", + "integrity": "sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY=", + "dev": true, + "optional": true, + "dependencies": { + "http-https": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "optional": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ganache-core/node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "dev": true, + "optional": true, + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/p-timeout/node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "optional": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/parse-headers": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", + "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/patch-package": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.2.2.tgz", + "integrity": "sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg==", + "dev": true, + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "find-yarn-workspace-root": "^1.2.1", + "fs-extra": "^7.0.1", + "is-ci": "^2.0.0", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.0", + "rimraf": "^2.6.3", + "semver": "^5.6.0", + "slash": "^2.0.0", + "tmp": "^0.0.33" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "npm": ">5" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/ganache-core/node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/ganache-core/node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "node_modules/ganache-core/node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/precond": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", + "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true, + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/ganache-core/node_modules/promise-to-callback": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/promise-to-callback/-/promise-to-callback-1.0.0.tgz", + "integrity": "sha1-XSp0kBC/tn2WNZj805YHRqaP7vc=", + "dev": true, + "dependencies": { + "is-fn": "^1.0.0", + "set-immediate-shim": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "optional": true, + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ganache-core/node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "node_modules/ganache-core/node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/ganache-core/node_modules/pull-cat": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/pull-cat/-/pull-cat-1.1.11.tgz", + "integrity": "sha1-tkLdElXaN2pwa220+pYvX9t0wxs=", + "dev": true + }, + "node_modules/ganache-core/node_modules/pull-defer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/pull-defer/-/pull-defer-0.2.3.tgz", + "integrity": "sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/pull-level": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pull-level/-/pull-level-2.0.4.tgz", + "integrity": "sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg==", + "dev": true, + "dependencies": { + "level-post": "^1.0.7", + "pull-cat": "^1.1.9", + "pull-live": "^1.0.1", + "pull-pushable": "^2.0.0", + "pull-stream": "^3.4.0", + "pull-window": "^2.1.4", + "stream-to-pull-stream": "^1.7.1" + } + }, + "node_modules/ganache-core/node_modules/pull-live": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pull-live/-/pull-live-1.0.1.tgz", + "integrity": "sha1-pOzuAeMwFV6RJLu89HYfIbOPUfU=", + "dev": true, + "dependencies": { + "pull-cat": "^1.1.9", + "pull-stream": "^3.4.0" + } + }, + "node_modules/ganache-core/node_modules/pull-pushable": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pull-pushable/-/pull-pushable-2.2.0.tgz", + "integrity": "sha1-Xy867UethpGfAbEqLpnW8b13ZYE=", + "dev": true + }, + "node_modules/ganache-core/node_modules/pull-stream": { + "version": "3.6.14", + "resolved": "https://registry.npmjs.org/pull-stream/-/pull-stream-3.6.14.tgz", + "integrity": "sha512-KIqdvpqHHaTUA2mCYcLG1ibEbu/LCKoJZsBWyv9lSYtPkJPBq8m3Hxa103xHi6D2thj5YXa0TqK3L3GUkwgnew==", + "dev": true + }, + "node_modules/ganache-core/node_modules/pull-window": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/pull-window/-/pull-window-2.1.4.tgz", + "integrity": "sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA=", + "dev": true, + "dependencies": { + "looper": "^2.0.0" + } + }, + "node_modules/ganache-core/node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/ganache-core/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ganache-core/node_modules/query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "optional": true, + "dependencies": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/ganache-core/node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "optional": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/ganache-core/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "optional": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/ganache-core/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/regenerate": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", + "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", + "dev": true + }, + "node_modules/ganache-core/node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "dependencies": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + }, + "node_modules/ganache-core/node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "dependencies": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "node_modules/ganache-core/node_modules/regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "node_modules/ganache-core/node_modules/regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/ganache-core/node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/ganache-core/node_modules/repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/ganache-core/node_modules/repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "dependencies": { + "is-finite": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ganache-core/node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + } + }, + "node_modules/ganache-core/node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "optional": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "dependencies": { + "through": "~2.3.4" + } + }, + "node_modules/ganache-core/node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/ganache-core/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ganache-core/node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/ganache-core/node_modules/rlp": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", + "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.1" + }, + "bin": { + "rlp": "bin/rlp" + } + }, + "node_modules/ganache-core/node_modules/rustbn.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", + "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/safe-event-emitter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz", + "integrity": "sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg==", + "dev": true, + "dependencies": { + "events": "^3.0.0" + } + }, + "node_modules/ganache-core/node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/ganache-core/node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/scryptsy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", + "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", + "dev": true, + "optional": true, + "dependencies": { + "pbkdf2": "^3.0.3" + } + }, + "node_modules/ganache-core/node_modules/secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ganache-core/node_modules/seedrandom": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.1.tgz", + "integrity": "sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ganache-core/node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "optional": true, + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ganache-core/node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "optional": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ganache-core/node_modules/servify": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", + "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "dev": true, + "optional": true, + "dependencies": { + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "request": "^2.79.0", + "xhr": "^2.3.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/set-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/ganache-core/node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "dev": true, + "optional": true, + "dependencies": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon-util/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/ganache-core/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/ganache-core/node_modules/source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/ganache-core/node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/sshpk/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/ganache-core/node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/stream-to-pull-stream": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz", + "integrity": "sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg==", + "dev": true, + "dependencies": { + "looper": "^3.0.0", + "pull-stream": "^3.2.3" + } + }, + "node_modules/ganache-core/node_modules/stream-to-pull-stream/node_modules/looper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/looper/-/looper-3.0.0.tgz", + "integrity": "sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k=", + "dev": true + }, + "node_modules/ganache-core/node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/ganache-core/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/string.prototype.trim": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.2.tgz", + "integrity": "sha512-b5yrbl3BXIjHau9Prk7U0RRYcUYdN4wGSVaqoBQS50CCE3KBuYU0TYRNPFCP7aVoNMX87HKThdMRVIP3giclKg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/string.prototype.trim/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/ganache-core/node_modules/string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/ganache-core/node_modules/strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "dev": true, + "dependencies": { + "is-hex-prefixed": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-core/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/swarm-js": { + "version": "0.1.40", + "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.40.tgz", + "integrity": "sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA==", + "dev": true, + "optional": true, + "dependencies": { + "bluebird": "^3.5.0", + "buffer": "^5.0.5", + "eth-lib": "^0.1.26", + "fs-extra": "^4.0.2", + "got": "^7.1.0", + "mime-types": "^2.1.16", + "mkdirp-promise": "^5.0.1", + "mock-fs": "^4.1.0", + "setimmediate": "^1.0.5", + "tar": "^4.0.2", + "xhr-request": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "optional": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true, + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "dev": true, + "optional": true, + "dependencies": { + "decompress-response": "^3.2.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-plain-obj": "^1.1.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "p-cancelable": "^0.3.0", + "p-timeout": "^1.1.1", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "url-parse-lax": "^1.0.0", + "url-to-options": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", + "dev": true, + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "optional": true, + "dependencies": { + "prepend-http": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/tape": { + "version": "4.13.3", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.13.3.tgz", + "integrity": "sha512-0/Y20PwRIUkQcTCSi4AASs+OANZZwqPKaipGCEwp10dQMipVvSZwUUCi01Y/OklIGyHKFhIcjock+DKnBfLAFw==", + "dev": true, + "dependencies": { + "deep-equal": "~1.1.1", + "defined": "~1.0.0", + "dotignore": "~0.1.2", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.6", + "has": "~1.0.3", + "inherits": "~2.0.4", + "is-regex": "~1.0.5", + "minimist": "~1.2.5", + "object-inspect": "~1.7.0", + "resolve": "~1.17.0", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.2.1", + "through": "~2.3.8" + }, + "bin": { + "tape": "bin/tape" + } + }, + "node_modules/ganache-core/node_modules/tape/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/tape/node_modules/is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/tape/node_modules/object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/ganache-core/node_modules/tar/node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "optional": true, + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/ganache-core/node_modules/tar/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "optional": true, + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/ganache-core/node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/ganache-core/node_modules/timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/tmp": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", + "dev": true, + "dependencies": { + "rimraf": "^2.6.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/to-object-path/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ganache-core/node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ganache-core/node_modules/trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/tweetnacl-util": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "optional": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/ganache-core/node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/typewise": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz", + "integrity": "sha1-EGeTZUCvl5N8xdz5kiSG6fooRlE=", + "dev": true, + "dependencies": { + "typewise-core": "^1.2.0" + } + }, + "node_modules/ganache-core/node_modules/typewise-core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz", + "integrity": "sha1-l+uRgFx/VdL5QXSPpQ0xXZke8ZU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/typewiselite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typewiselite/-/typewiselite-1.0.0.tgz", + "integrity": "sha1-yIgvobsQksBgBal/NO9chQjjZk4=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/union-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/ganache-core/node_modules/unorm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", + "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/ganache-core/node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/ganache-core/node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "node_modules/ganache-core/node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "optional": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/url-set-query": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", + "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ganache-core/node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/utf-8-validate": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz", + "integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "~3.7.0" + } + }, + "node_modules/ganache-core/node_modules/utf-8-validate/node_modules/node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/ganache-core/node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "node_modules/ganache-core/node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/ganache-core/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/ganache-core/node_modules/varint": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", + "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/ganache-core/node_modules/web3": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.11.tgz", + "integrity": "sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "dependencies": { + "web3-bzz": "1.2.11", + "web3-core": "1.2.11", + "web3-eth": "1.2.11", + "web3-eth-personal": "1.2.11", + "web3-net": "1.2.11", + "web3-shh": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-bzz": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.11.tgz", + "integrity": "sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "^12.12.6", + "got": "9.6.0", + "swarm-js": "^0.1.40", + "underscore": "1.9.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-bzz/node_modules/@types/node": { + "version": "12.12.67", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz", + "integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/web3-core": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.11.tgz", + "integrity": "sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ==", + "dev": true, + "optional": true, + "dependencies": { + "@types/bn.js": "^4.11.5", + "@types/node": "^12.12.6", + "bignumber.js": "^9.0.0", + "web3-core-helpers": "1.2.11", + "web3-core-method": "1.2.11", + "web3-core-requestmanager": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-core-helpers": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz", + "integrity": "sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A==", + "dev": true, + "optional": true, + "dependencies": { + "underscore": "1.9.1", + "web3-eth-iban": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-core-method": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.11.tgz", + "integrity": "sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/transactions": "^5.0.0-beta.135", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.11", + "web3-core-promievent": "1.2.11", + "web3-core-subscriptions": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-core-promievent": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz", + "integrity": "sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA==", + "dev": true, + "optional": true, + "dependencies": { + "eventemitter3": "4.0.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-core-requestmanager": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz", + "integrity": "sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA==", + "dev": true, + "optional": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.11", + "web3-providers-http": "1.2.11", + "web3-providers-ipc": "1.2.11", + "web3-providers-ws": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-core-subscriptions": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz", + "integrity": "sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg==", + "dev": true, + "optional": true, + "dependencies": { + "eventemitter3": "4.0.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-core/node_modules/@types/node": { + "version": "12.12.67", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz", + "integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/web3-eth": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.11.tgz", + "integrity": "sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ==", + "dev": true, + "optional": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core": "1.2.11", + "web3-core-helpers": "1.2.11", + "web3-core-method": "1.2.11", + "web3-core-subscriptions": "1.2.11", + "web3-eth-abi": "1.2.11", + "web3-eth-accounts": "1.2.11", + "web3-eth-contract": "1.2.11", + "web3-eth-ens": "1.2.11", + "web3-eth-iban": "1.2.11", + "web3-eth-personal": "1.2.11", + "web3-net": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-abi": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz", + "integrity": "sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/abi": "5.0.0-beta.153", + "underscore": "1.9.1", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-accounts": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz", + "integrity": "sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw==", + "dev": true, + "optional": true, + "dependencies": { + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.8", + "ethereumjs-common": "^1.3.2", + "ethereumjs-tx": "^2.1.1", + "scrypt-js": "^3.0.1", + "underscore": "1.9.1", + "uuid": "3.3.2", + "web3-core": "1.2.11", + "web3-core-helpers": "1.2.11", + "web3-core-method": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-accounts/node_modules/eth-lib": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-accounts/node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true, + "optional": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-contract": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz", + "integrity": "sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow==", + "dev": true, + "optional": true, + "dependencies": { + "@types/bn.js": "^4.11.5", + "underscore": "1.9.1", + "web3-core": "1.2.11", + "web3-core-helpers": "1.2.11", + "web3-core-method": "1.2.11", + "web3-core-promievent": "1.2.11", + "web3-core-subscriptions": "1.2.11", + "web3-eth-abi": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-ens": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz", + "integrity": "sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA==", + "dev": true, + "optional": true, + "dependencies": { + "content-hash": "^2.5.2", + "eth-ens-namehash": "2.0.8", + "underscore": "1.9.1", + "web3-core": "1.2.11", + "web3-core-helpers": "1.2.11", + "web3-core-promievent": "1.2.11", + "web3-eth-abi": "1.2.11", + "web3-eth-contract": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-iban": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz", + "integrity": "sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.11.9", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-personal": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz", + "integrity": "sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "^12.12.6", + "web3-core": "1.2.11", + "web3-core-helpers": "1.2.11", + "web3-core-method": "1.2.11", + "web3-net": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-personal/node_modules/@types/node": { + "version": "12.12.67", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz", + "integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/web3-net": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.11.tgz", + "integrity": "sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg==", + "dev": true, + "optional": true, + "dependencies": { + "web3-core": "1.2.11", + "web3-core-method": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz", + "integrity": "sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw==", + "dev": true, + "dependencies": { + "async": "^2.5.0", + "backoff": "^2.5.0", + "clone": "^2.0.0", + "cross-fetch": "^2.1.0", + "eth-block-tracker": "^3.0.0", + "eth-json-rpc-infura": "^3.1.0", + "eth-sig-util": "^1.4.2", + "ethereumjs-block": "^1.2.2", + "ethereumjs-tx": "^1.2.0", + "ethereumjs-util": "^5.1.5", + "ethereumjs-vm": "^2.3.4", + "json-rpc-error": "^2.0.0", + "json-stable-stringify": "^1.0.1", + "promise-to-callback": "^1.0.0", + "readable-stream": "^2.2.9", + "request": "^2.85.0", + "semaphore": "^1.0.3", + "ws": "^5.1.1", + "xhr": "^2.2.0", + "xtend": "^4.0.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.6.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/eth-sig-util": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz", + "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", + "dev": true, + "dependencies": { + "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git", + "ethereumjs-util": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-abi": { + "resolved": "git+https://git@github.com/ethereumjs/ethereumjs-abi.git#1ce6a1d64235fabe2aaf827fd606def55693508f", + "dev": true, + "dependencies": { + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-account": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", + "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", + "dev": true, + "dependencies": { + "ethereumjs-util": "^5.0.0", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-block": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "^1.2.2", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-block/node_modules/ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-tx": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", + "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", + "dev": true, + "dependencies": { + "ethereum-common": "^0.0.18", + "ethereumjs-util": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz", + "integrity": "sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "async-eventemitter": "^0.2.2", + "ethereumjs-account": "^2.0.3", + "ethereumjs-block": "~2.2.0", + "ethereumjs-common": "^1.1.0", + "ethereumjs-util": "^6.0.0", + "fake-merkle-patricia-tree": "^1.0.1", + "functional-red-black-tree": "^1.0.1", + "merkle-patricia-tree": "^2.3.2", + "rustbn.js": "~0.2.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm/node_modules/ethereumjs-block": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", + "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm/node_modules/ethereumjs-block/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm/node_modules/ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "dev": true, + "dependencies": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-ws/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-ws/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-providers-http": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.11.tgz", + "integrity": "sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA==", + "dev": true, + "optional": true, + "dependencies": { + "web3-core-helpers": "1.2.11", + "xhr2-cookies": "1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-providers-ipc": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz", + "integrity": "sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ==", + "dev": true, + "optional": true, + "dependencies": { + "oboe": "2.1.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-providers-ws": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz", + "integrity": "sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg==", + "dev": true, + "optional": true, + "dependencies": { + "eventemitter3": "4.0.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.11", + "websocket": "^1.0.31" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-shh": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.11.tgz", + "integrity": "sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg==", + "dev": true, + "optional": true, + "dependencies": { + "web3-core": "1.2.11", + "web3-core-method": "1.2.11", + "web3-core-subscriptions": "1.2.11", + "web3-net": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-utils": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.11.tgz", + "integrity": "sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-utils/node_modules/eth-lib": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/ganache-core/node_modules/websocket": { + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.32.tgz", + "integrity": "sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q==", + "dev": true, + "dependencies": { + "bufferutil": "^4.0.1", + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/ganache-core/node_modules/websocket/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/websocket/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/ganache-core/node_modules/whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==", + "dev": true + }, + "node_modules/ganache-core/node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "optional": true, + "dependencies": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, + "node_modules/ganache-core/node_modules/ws/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/xhr": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", + "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "dev": true, + "dependencies": { + "global": "~4.3.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/xhr-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", + "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "dev": true, + "optional": true, + "dependencies": { + "buffer-to-arraybuffer": "^0.0.5", + "object-assign": "^4.1.1", + "query-string": "^5.0.1", + "simple-get": "^2.7.0", + "timed-out": "^4.0.1", + "url-set-query": "^1.0.0", + "xhr": "^2.0.4" + } + }, + "node_modules/ganache-core/node_modules/xhr-request-promise": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz", + "integrity": "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==", + "dev": true, + "optional": true, + "dependencies": { + "xhr-request": "^1.1.0" + } + }, + "node_modules/ganache-core/node_modules/xhr2-cookies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", + "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", + "dev": true, + "optional": true, + "dependencies": { + "cookiejar": "^2.1.1" + } + }, + "node_modules/ganache-core/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ganache-core/node_modules/yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", + "dev": true, + "engines": { + "node": ">=0.10.32" + } + }, + "node_modules/ganache-core/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", + "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "node_modules/get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "dev": true, + "dependencies": { + "npm-conf": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/ghost-testrpc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", + "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "node-emoji": "^1.10.0" + }, + "bin": { + "testrpc-sc": "index.js" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "dev": true, + "dependencies": { + "min-document": "^2.19.0", + "process": "~0.5.1" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/globby": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hardhat": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.0.8.tgz", + "integrity": "sha512-2tDAtOfshrBzP103dx7PQrhTwv2sqjhQStZAPwkkQTic25o2EH6HYE2++LuOG98YwqSjr0WvhvdBvKl3dCSkYA==", + "dev": true, + "dependencies": { + "@nomiclabs/ethereumjs-vm": "^4.1.1", + "@sentry/node": "^5.18.1", + "@solidity-parser/parser": "^0.11.0", + "@types/bn.js": "^4.11.5", + "@types/lru-cache": "^5.1.0", + "abort-controller": "^3.0.0", + "adm-zip": "^0.4.16", + "ansi-escapes": "^4.3.0", + "chalk": "^2.4.2", + "chokidar": "^3.4.0", + "ci-info": "^2.0.0", + "debug": "^4.1.1", + "enquirer": "^2.3.0", + "env-paths": "^2.2.0", + "eth-sig-util": "^2.5.2", + "ethereum-cryptography": "^0.1.2", + "ethereumjs-abi": "^0.6.8", + "ethereumjs-account": "^3.0.0", + "ethereumjs-block": "^2.2.0", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^6.1.0", + "find-up": "^2.1.0", + "fp-ts": "1.19.3", + "fs-extra": "^7.0.1", + "glob": "^7.1.3", + "immutable": "^4.0.0-rc.12", + "io-ts": "1.10.4", + "lodash": "^4.17.11", + "merkle-patricia-tree": "^3.0.0", + "mocha": "^7.1.2", + "node-fetch": "^2.6.0", + "qs": "^6.7.0", + "raw-body": "^2.4.1", + "resolve": "1.17.0", + "semver": "^6.3.0", + "slash": "^3.0.0", + "solc": "0.7.3", + "source-map-support": "^0.5.13", + "stacktrace-parser": "^0.1.10", + "true-case-path": "^2.2.1", + "tsort": "0.0.1", + "uuid": "^3.3.2", + "ws": "^7.2.1" + }, + "bin": { + "hardhat": "internal/cli/cli.js" + }, + "engines": { + "node": ">=8.2.0" + } + }, + "node_modules/hardhat-gas-reporter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.1.tgz", + "integrity": "sha512-YC+SCYIkBdRtISNbisU2BwDSelUdCrIKRsJXt3M9Jw1VF5CmtSZb8VuuOc2Zl4AMcEV2jEy6ZuAksYomPiApYQ==", + "dev": true, + "dependencies": { + "eth-gas-reporter": "^0.2.19" + } + }, + "node_modules/hardhat-typechain": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/hardhat-typechain/-/hardhat-typechain-0.3.3.tgz", + "integrity": "sha512-NrqP7Zng28prV3YT0lXoo1pXtZxoNCMfiZIWkf1HXjjID42JLLfSOTsvlb0okDMpz4tJaEEkgADJO69sKZxw+Q==", + "dev": true + }, + "node_modules/hardhat/node_modules/@solidity-parser/parser": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.11.1.tgz", + "integrity": "sha512-H8BSBoKE8EubJa0ONqecA2TviT3TnHeC4NpgnAHSUiuhZoQBfPB4L2P9bs8R6AoTW10Endvh3vc+fomVMIDIYQ==", + "dev": true + }, + "node_modules/hardhat/node_modules/commander": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "dev": true + }, + "node_modules/hardhat/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/hardhat/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/hardhat/node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + } + }, + "node_modules/hardhat/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/hardhat/node_modules/solc": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", + "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", + "dev": true, + "dependencies": { + "command-exists": "^1.2.8", + "commander": "3.0.2", + "follow-redirects": "^1.12.1", + "fs-extra": "^0.30.0", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "require-from-string": "^2.0.0", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solcjs" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/hardhat/node_modules/solc/node_modules/fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/hardhat/node_modules/solc/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/hardhat/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dev": true, + "dependencies": { + "has-symbol-support-x": "^1.4.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/has-values/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "node_modules/http-basic": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", + "integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==", + "dev": true, + "dependencies": { + "caseless": "^0.12.0", + "concat-stream": "^1.6.2", + "http-response-object": "^3.0.1", + "parse-cache-control": "^1.0.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "node_modules/http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", + "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=", + "dev": true + }, + "node_modules/http-response-object": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", + "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", + "dev": true, + "dependencies": { + "@types/node": "^10.0.3" + } + }, + "node_modules/http-response-object/node_modules/@types/node": { + "version": "10.17.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", + "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "dev": true + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/husky": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz", + "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "compare-versions": "^3.6.0", + "cosmiconfig": "^7.0.0", + "find-versions": "^3.2.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "slash": "^3.0.0", + "which-pm-runs": "^1.0.0" + }, + "bin": { + "husky-run": "bin/run.js", + "husky-upgrade": "lib/upgrader/bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/husky/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/husky/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/husky/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/husky/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/husky/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/husky/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/idna-uts46-hx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", + "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", + "dev": true, + "dependencies": { + "punycode": "2.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", + "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", + "dev": true + }, + "node_modules/immutable": { + "version": "4.0.0-rc.12", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz", + "integrity": "sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", + "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "dev": true, + "dependencies": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/io-ts": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", + "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", + "dev": true, + "dependencies": { + "fp-ts": "^1.0.0" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz", + "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "dev": true + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", + "dev": true, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/is-installed-globally": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.2.0.tgz", + "integrity": "sha512-g3TzWCnR/eO4Q3abCwgFjOFw7uVOfxG4m8hMr/39Jcf2YvE5mHrFKqpyuraWV4zwx9XhjnVO4nY0ZI4llzl0Pg==", + "dev": true, + "dependencies": { + "global-dirs": "^0.1.1", + "is-path-inside": "^2.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", + "dev": true + }, + "node_modules/is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, + "node_modules/is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "node_modules/isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true, + "dependencies": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/jest-docblock": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz", + "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==", + "dev": true + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonschema": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz", + "integrity": "sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/keccak": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", + "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", + "dev": true + }, + "node_modules/level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + } + }, + "node_modules/level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + } + }, + "node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/level-iterator-stream/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/level-iterator-stream/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/level-mem": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-3.0.1.tgz", + "integrity": "sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg==", + "dev": true, + "dependencies": { + "level-packager": "~4.0.0", + "memdown": "~3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-mem/node_modules/abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-mem/node_modules/immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", + "dev": true + }, + "node_modules/level-mem/node_modules/memdown": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz", + "integrity": "sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~5.0.0", + "functional-red-black-tree": "~1.0.1", + "immediate": "~3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-mem/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/level-mem/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/level-packager": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-4.0.1.tgz", + "integrity": "sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q==", + "dev": true, + "dependencies": { + "encoding-down": "~5.0.0", + "levelup": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager/node_modules/abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager/node_modules/deferred-leveldown": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", + "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~5.0.0", + "inherits": "^2.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/level-packager/node_modules/level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager/node_modules/level-iterator-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", + "integrity": "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager/node_modules/levelup": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz", + "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~4.0.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~3.0.0", + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/level-packager/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/level-packager/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/level-packager/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + } + }, + "node_modules/level-ws/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/level-ws/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "node_modules/levelup/node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/levelup/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "node_modules/lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true + }, + "node_modules/lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lowdb": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz", + "integrity": "sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.3", + "is-promise": "^2.1.0", + "lodash": "4", + "pify": "^3.0.0", + "steno": "^0.4.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru_map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", + "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=", + "dev": true + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-table": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", + "dev": true + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/memdown/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/memdown/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/merkle-patricia-tree": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz", + "integrity": "sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ==", + "dev": true, + "dependencies": { + "async": "^2.6.1", + "ethereumjs-util": "^5.2.0", + "level-mem": "^3.0.1", + "level-ws": "^1.0.0", + "readable-stream": "^3.0.6", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/merkle-patricia-tree/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/merkle-patricia-tree/node_modules/level-ws": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-1.0.0.tgz", + "integrity": "sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.2.8", + "xtend": "^4.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/merkle-patricia-tree/node_modules/level-ws/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/merkle-patricia-tree/node_modules/level-ws/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/merkle-patricia-tree/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/merkle-patricia-tree/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/merkle-patricia-tree/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/micromatch/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "dependencies": { + "mime-db": "1.44.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "dev": true, + "dependencies": { + "dom-walk": "^0.1.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-promise": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", + "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", + "dev": true, + "dependencies": { + "mkdirp": "*" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mocha": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", + "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", + "dev": true, + "dependencies": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.5", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 8.10.0" + } + }, + "node_modules/mocha/node_modules/ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.1.1" + } + }, + "node_modules/mocha/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/mocha/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/mocha/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mocha/node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mocha/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mock-fs": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.13.0.tgz", + "integrity": "sha512-DD0vOdofJdoaRNtnWcrXe6RQbpHkPPmtqGq14uRX0F8ZKJ5nv89CVTYl/BZdppDxBDaV0hl75htg3abpEWlPZA==", + "dev": true + }, + "node_modules/mri": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", + "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "dependencies": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true + }, + "node_modules/nano-json-stream-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", + "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=", + "dev": true + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "dev": true + }, + "node_modules/node-emoji": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", + "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==", + "dev": true, + "dependencies": { + "lodash.toarray": "^4.4.0" + } + }, + "node_modules/node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "dependencies": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node_modules/node-environment-flags/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-gyp-build": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/nofilter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-1.0.4.tgz", + "integrity": "sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/normalize-url/node_modules/sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true, + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "dev": true, + "dependencies": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz", + "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", + "dev": true, + "dependencies": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/number-to-bn/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/oboe": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.4.tgz", + "integrity": "sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY=", + "dev": true, + "dependencies": { + "http-https": "^1.0.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true, + "bin": { + "opencollective-postinstall": "index.js" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-event": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", + "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", + "dev": true, + "dependencies": { + "p-timeout": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "dev": true, + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-cache-control": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", + "integrity": "sha1-juqz5U+laSD+Fro493+iGqzC104=", + "dev": true + }, + "node_modules/parse-code-context": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-code-context/-/parse-code-context-1.0.0.tgz", + "integrity": "sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-headers": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", + "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==", + "dev": true + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/patch-package": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.2.2.tgz", + "integrity": "sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg==", + "dev": true, + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "find-yarn-workspace-root": "^1.2.1", + "fs-extra": "^7.0.1", + "is-ci": "^2.0.0", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.0", + "rimraf": "^2.6.3", + "semver": "^5.6.0", + "slash": "^2.0.0", + "tmp": "^0.0.33" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/patch-package/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/patch-package/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/patch-package/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-type/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "dependencies": { + "semver-compare": "^1.0.0" + } + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postinstall-postinstall": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz", + "integrity": "sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ==", + "dev": true, + "hasInstallScript": true + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", + "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/prettier-plugin-solidity": { + "version": "1.0.0-alpha.60", + "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-alpha.60.tgz", + "integrity": "sha512-Dd6T0dVfw0kJrlEnLDFFE3mKRSP7zpT6zcIWvnSW+z4NBl+gmwJ7UJRZHD0CNDD6N48c+zb28xs3oF0ylDaYyg==", + "dev": true, + "dependencies": { + "@solidity-parser/parser": "^0.9.0", + "dir-to-object": "^2.0.0", + "emoji-regex": "^9.0.0", + "escape-string-regexp": "^4.0.0", + "extract-comments": "^1.1.0", + "prettier": "^2.0.5", + "semver": "^7.3.2", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/@solidity-parser/parser": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.9.0.tgz", + "integrity": "sha512-u1WzZgzOBFsGAcUhyj8DN/kop1SvrsaRT2ZVvDpVYnFI86YwbLrXCTGxefJzYGnA5Vajbbhi4aRtlxxFh69dfA==", + "dev": true, + "dependencies": { + "antlr4": "^4.8.0" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/emoji-regex": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.0.tgz", + "integrity": "sha512-DNc3KFPK18bPdElMJnf/Pkv5TXhxFU3YFDEuGLDRtPmV4rkmCjBkCSEp22u6rBHdSN9Vlp/GK7k98prmE1Jgug==", + "dev": true + }, + "node_modules/prettier-plugin-solidity/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/prettier-plugin-solidity/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-2.0.2.tgz", + "integrity": "sha512-aLb6vtOTEfJDwi1w+MBTeE20GwPVUYyn6IqNg6TtGpiOB1W3y6vKcsGFjqGeaaEtQgMLSPXTWONqh33UBuwG8A==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "execa": "^2.1.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.4", + "multimatch": "^4.0.0" + }, + "bin": { + "pretty-quick": "bin/pretty-quick.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pretty-quick/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pretty-quick/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/promise": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", + "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", + "dev": true, + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, + "node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", + "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "dependencies": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomhex": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", + "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=", + "dev": true + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", + "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.3", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", + "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "dev": true, + "dependencies": { + "minimatch": "3.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/req-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", + "integrity": "sha1-1AgrTURZgDZkD7c93qAe1T20nrw=", + "dev": true, + "dependencies": { + "req-from": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/req-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/req-from/-/req-from-2.0.0.tgz", + "integrity": "sha1-10GI5H+TeW9Kpx327jWuaJ8+DnA=", + "dev": true, + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request-promise-core": { + "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, + "dependencies": { + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/request-promise-native": { + "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, + "dependencies": { + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + }, + "node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rlp": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", + "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.1" + }, + "bin": { + "rlp": "bin/rlp" + } + }, + "node_modules/run-parallel": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", + "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", + "dev": true + }, + "node_modules/rustbn.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", + "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sc-istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.5.tgz", + "integrity": "sha512-7wR5EZFLsC4w0wSm9BUuCgW+OGKAU7PNlW5L0qwVPbh+Q1sfVn2fyzfMXYCm6rkNA5ipaCOt94nApcguQwF5Gg==", + "dev": true, + "dependencies": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "istanbul": "lib/cli.js" + } + }, + "node_modules/sc-istanbul/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/sc-istanbul/node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sc-istanbul/node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/sc-istanbul/node_modules/has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sc-istanbul/node_modules/resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "node_modules/sc-istanbul/node_modules/supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "dev": true + }, + "node_modules/scrypt-shim": { + "resolved": "git+ssh://git@github.com/web3-js/scrypt-shim.git#aafdadda13e660e25e1c525d1f5b2443f5eb1ebb", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "scryptsy": "^2.1.0", + "semver": "^6.3.0" + } + }, + "node_modules/scryptsy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz", + "integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==", + "dev": true + }, + "node_modules/secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "dev": true, + "dependencies": { + "commander": "^2.8.1" + }, + "bin": { + "seek-bunzip": "bin/seek-bunzip", + "seek-table": "bin/seek-bzip-table" + } + }, + "node_modules/semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "node_modules/semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/servify": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", + "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "dev": true, + "dependencies": { + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "request": "^2.79.0", + "xhr": "^2.3.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/sha1": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", + "integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=", + "dev": true, + "dependencies": { + "charenc": ">= 0.0.1", + "crypt": ">= 0.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shelljs": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "dev": true, + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true + }, + "node_modules/simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "dev": true, + "dependencies": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/solc": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.6.8.tgz", + "integrity": "sha512-7URBAisWVjO7dwWNpEkQ5dpRSpSF4Wm0aD5EB82D5BQKh+q7jhOxhgkG4K5gax/geM0kPZUAxnaLcgl2ZXBgMQ==", + "dev": true, + "dependencies": { + "command-exists": "^1.2.8", + "commander": "3.0.2", + "fs-extra": "^0.30.0", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "require-from-string": "^2.0.0", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solcjs" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/solc/node_modules/commander": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "dev": true + }, + "node_modules/solc/node_modules/fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/solc/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/solc/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/solc/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/solc/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/solidity-coverage": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.10.tgz", + "integrity": "sha512-F98rYoD3bscB9qIJJrqkk+o93GbOWTT54VgfO97PrcWAenOFIC1EI5DzGJSrMvmFFfr8fsMPR89on6JR0Xf/Ig==", + "dev": true, + "dependencies": { + "@solidity-parser/parser": "^0.7.0", + "@truffle/provider": "^0.1.17", + "chalk": "^2.4.2", + "death": "^1.1.0", + "detect-port": "^1.3.0", + "fs-extra": "^8.1.0", + "ganache-cli": "6.9.0", + "ghost-testrpc": "^0.0.2", + "global-modules": "^2.0.0", + "globby": "^10.0.1", + "jsonschema": "^1.2.4", + "lodash": "^4.17.15", + "node-emoji": "^1.10.0", + "pify": "^4.0.1", + "recursive-readdir": "^2.2.2", + "sc-istanbul": "^0.4.5", + "shelljs": "^0.8.3", + "web3": "1.2.6" + }, + "bin": { + "solidity-coverage": "plugins/bin.js" + } + }, + "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.7.1.tgz", + "integrity": "sha512-5ma2uuwPAEX1TPl2rAPAAuGlBkKnn2oUKQvnhTFlDIB8U/KDWX77FpHtL6Rcz+OwqSCWx9IClxACgyIEJ/GhIw==", + "dev": true + }, + "node_modules/solidity-coverage/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/solidity-coverage/node_modules/globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/solidity-coverage/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", + "dev": true, + "dependencies": { + "sort-keys": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "dev": true + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/stacktrace-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", + "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "dev": true, + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stacktrace-parser/node_modules/type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/steno": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", + "integrity": "sha1-BxEFvfwobmYVwEA8J+nXtdy4Vcs=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.3" + } + }, + "node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", + "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "node_modules/string.prototype.trimend/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.trimend/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", + "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "node_modules/string.prototype.trimstart/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.trimstart/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "dev": true, + "dependencies": { + "is-natural-number": "^4.0.1" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "dev": true, + "dependencies": { + "is-hex-prefixed": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/swarm-js": { + "version": "0.1.39", + "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.39.tgz", + "integrity": "sha512-QLMqL2rzF6n5s50BptyD6Oi0R1aWlJC5Y17SRIVXRj6OR1DRIPM7nepvrxxkjA1zNzFz6mUOMjfeqeDaWB7OOg==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.0", + "buffer": "^5.0.5", + "decompress": "^4.0.0", + "eth-lib": "^0.1.26", + "fs-extra": "^4.0.2", + "got": "^7.1.0", + "mime-types": "^2.1.16", + "mkdirp-promise": "^5.0.1", + "mock-fs": "^4.1.0", + "setimmediate": "^1.0.5", + "tar": "^4.0.2", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/swarm-js/node_modules/eth-lib": { + "version": "0.1.29", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz", + "integrity": "sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "nano-json-stream-parser": "^0.1.2", + "servify": "^0.1.12", + "ws": "^3.0.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/swarm-js/node_modules/fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/swarm-js/node_modules/got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "dev": true, + "dependencies": { + "decompress-response": "^3.2.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-plain-obj": "^1.1.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "p-cancelable": "^0.3.0", + "p-timeout": "^1.1.1", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "url-parse-lax": "^1.0.0", + "url-to-options": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/swarm-js/node_modules/p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/swarm-js/node_modules/p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "dev": true, + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/swarm-js/node_modules/prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/swarm-js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/swarm-js/node_modules/url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "dependencies": { + "prepend-http": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/swarm-js/node_modules/ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, + "node_modules/sync-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", + "integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==", + "dev": true, + "dependencies": { + "http-response-object": "^3.0.1", + "sync-rpc": "^1.2.1", + "then-request": "^6.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/sync-rpc": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz", + "integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==", + "dev": true, + "dependencies": { + "get-port": "^3.1.0" + } + }, + "node_modules/tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dev": true, + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/tar-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/tar-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/tar-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/tar-stream/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/temp-hardhat-etherscan": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/temp-hardhat-etherscan/-/temp-hardhat-etherscan-2.0.2.tgz", + "integrity": "sha512-q9+OMPXlsXZ+2fnF+Xmvv0J9vNJChwOXVGJIATiDJr7Qe8LzTwgs55C4l4NKMWPLe4PE9UjcQMVntRfXGTF9vA==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.0.2", + "@ethersproject/address": "^5.0.2", + "cbor": "^5.0.2", + "fs-extra": "^7.0.1", + "lodash": "^4.17.11", + "node-fetch": "^2.6.0", + "semver": "^6.3.0" + } + }, + "node_modules/test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", + "dev": true, + "dependencies": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/test-value/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/testrpc": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/testrpc/-/testrpc-0.0.1.tgz", + "integrity": "sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA==", + "dev": true + }, + "node_modules/then-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", + "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", + "dev": true, + "dependencies": { + "@types/concat-stream": "^1.6.0", + "@types/form-data": "0.0.33", + "@types/node": "^8.0.0", + "@types/qs": "^6.2.31", + "caseless": "~0.12.0", + "concat-stream": "^1.6.0", + "form-data": "^2.2.0", + "http-basic": "^8.1.1", + "http-response-object": "^3.0.1", + "promise": "^8.0.0", + "qs": "^6.4.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/then-request/node_modules/@types/node": { + "version": "8.10.66", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", + "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.2.tgz", + "integrity": "sha512-OyCLAKU1HzBjL6Ev3gxUeraJNlbNingmi8IrHHEsYH8LTmEuhvYfqvhn2F/je+mjf4N58UmZ96OMEy1JanSCpA==", + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "dev": true + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tough-cookie/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/true-case-path": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-2.2.1.tgz", + "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==", + "dev": true + }, + "node_modules/ts-essentials": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-2.0.12.tgz", + "integrity": "sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w==", + "dev": true + }, + "node_modules/ts-generator": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ts-generator/-/ts-generator-0.1.1.tgz", + "integrity": "sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ==", + "dev": true, + "dependencies": { + "@types/mkdirp": "^0.5.2", + "@types/prettier": "^2.1.1", + "@types/resolve": "^0.0.8", + "chalk": "^2.4.1", + "glob": "^7.1.2", + "mkdirp": "^0.5.1", + "prettier": "^2.1.2", + "resolve": "^1.8.1", + "ts-essentials": "^1.0.0" + }, + "bin": { + "ts-generator": "dist/cli/run.js" + } + }, + "node_modules/ts-generator/node_modules/ts-essentials": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-1.0.4.tgz", + "integrity": "sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ==", + "dev": true + }, + "node_modules/ts-node": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", + "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", + "dev": true, + "dependencies": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + } + }, + "node_modules/tslint-config-prettier": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", + "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", + "dev": true, + "bin": { + "tslint-config-prettier-check": "bin/check.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/tslint-plugin-prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslint-plugin-prettier/-/tslint-plugin-prettier-2.3.0.tgz", + "integrity": "sha512-F9e4K03yc9xuvv+A0v1EmjcnDwpz8SpCD8HzqSDe0eyg34cBinwn9JjmnnRrNAs4HdleRQj7qijp+P/JTxt4vA==", + "dev": true, + "dependencies": { + "eslint-plugin-prettier": "^2.2.0", + "lines-and-columns": "^1.1.6", + "tslib": "^1.7.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/tslint/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tslint/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/tsort": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", + "integrity": "sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=", + "dev": true + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "dev": true + }, + "node_modules/tweetnacl-util": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", + "dev": true + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typechain": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-4.0.0.tgz", + "integrity": "sha512-XQUojf02bXyxXNGI0WeCphnh++5eWr9wYH8jm0XqHNv8yENpFrRyX8ffVlkhCnDOOB/jEJJVQytLAOU+Qn0N9Q==", + "dev": true, + "dependencies": { + "command-line-args": "^4.0.7", + "debug": "^4.1.1", + "fs-extra": "^7.0.0", + "js-sha3": "^0.8.0", + "lodash": "^4.17.15", + "ts-essentials": "^6.0.3", + "ts-generator": "^0.1.1" + }, + "bin": { + "typechain": "dist/cli/cli.js" + } + }, + "node_modules/typechain/node_modules/ts-essentials": { + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-6.0.7.tgz", + "integrity": "sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw==", + "dev": true + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", + "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.6.tgz", + "integrity": "sha512-oASI1FOJ7BBFkSCNDZ446EgkSuHkOZBuqRFrwXIKWCoXw8ZXQETooTQjkAcBS03Acab7ubCKsXnwuV2svy061g==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/url-set-query": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", + "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=", + "dev": true + }, + "node_modules/url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/web3": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.6.tgz", + "integrity": "sha512-tpu9fLIComgxGrFsD8LUtA4s4aCZk7px8UfcdEy6kS2uDi/ZfR07KJqpXZMij7Jvlq+cQrTAhsPSiBVvoMaivA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@types/node": "^12.6.1", + "web3-bzz": "1.2.6", + "web3-core": "1.2.6", + "web3-eth": "1.2.6", + "web3-eth-personal": "1.2.6", + "web3-net": "1.2.6", + "web3-shh": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-bzz": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.2.tgz", + "integrity": "sha512-b1O2ObsqUN1lJxmFSjvnEC4TsaCbmh7Owj3IAIWTKqL9qhVgx7Qsu5O9cD13pBiSPNZJ68uJPaKq380QB4NWeA==", + "dev": true, + "dependencies": { + "@types/node": "^10.12.18", + "got": "9.6.0", + "swarm-js": "0.1.39", + "underscore": "1.9.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-bzz/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3-bzz/node_modules/@types/node": { + "version": "10.17.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", + "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "dev": true + }, + "node_modules/web3-bzz/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3-bzz/node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3-bzz/node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3-bzz/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3-bzz/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/web3-bzz/node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/web3-bzz/node_modules/normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3-bzz/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3-core": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.2.tgz", + "integrity": "sha512-miHAX3qUgxV+KYfaOY93Hlc3kLW2j5fH8FJy6kSxAv+d4d5aH0wwrU2IIoJylQdT+FeenQ38sgsCnFu9iZ1hCQ==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.4", + "@types/node": "^12.6.1", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-requestmanager": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-helpers": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.2.tgz", + "integrity": "sha512-HJrRsIGgZa1jGUIhvGz4S5Yh6wtOIo/TMIsSLe+Xay+KVnbseJpPprDI5W3s7H2ODhMQTbogmmUFquZweW2ImQ==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-eth-iban": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-helpers/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-core-helpers/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-core-helpers/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-method": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.2.tgz", + "integrity": "sha512-szR4fDSBxNHaF1DFqE+j6sFR/afv9Aa36OW93saHZnrh+iXSrYeUUDfugeNcRlugEKeUCkd4CZylfgbK2SKYJA==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2", + "web3-core-promievent": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-method/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-core-method/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-core-method/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-promievent": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.2.tgz", + "integrity": "sha512-tKvYeT8bkUfKABcQswK6/X79blKTKYGk949urZKcLvLDEaWrM3uuzDwdQT3BNKzQ3vIvTggFPX9BwYh0F1WwqQ==", + "dev": true, + "dependencies": { + "any-promise": "1.3.0", + "eventemitter3": "3.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-requestmanager": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.2.tgz", + "integrity": "sha512-a+gSbiBRHtHvkp78U2bsntMGYGF2eCb6219aMufuZWeAZGXJ63Wc2321PCbA8hF9cQrZI4EoZ4kVLRI4OF15Hw==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2", + "web3-providers-http": "1.2.2", + "web3-providers-ipc": "1.2.2", + "web3-providers-ws": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-subscriptions": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.2.tgz", + "integrity": "sha512-QbTgigNuT4eicAWWr7ahVpJyM8GbICsR1Ys9mJqzBEwpqS+RXTRVSkwZ2IsxO+iqv6liMNwGregbJLq4urMFcQ==", + "dev": true, + "dependencies": { + "eventemitter3": "3.1.2", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core/node_modules/@types/node": { + "version": "12.19.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", + "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", + "dev": true + }, + "node_modules/web3-core/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-core/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-core/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.2.tgz", + "integrity": "sha512-UXpC74mBQvZzd4b+baD4Ocp7g+BlwxhBHumy9seyE/LMIcMlePXwCKzxve9yReNpjaU16Mmyya6ZYlyiKKV8UA==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-eth-abi": "1.2.2", + "web3-eth-accounts": "1.2.2", + "web3-eth-contract": "1.2.2", + "web3-eth-ens": "1.2.2", + "web3-eth-iban": "1.2.2", + "web3-eth-personal": "1.2.2", + "web3-net": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-abi": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.2.tgz", + "integrity": "sha512-Yn/ZMgoOLxhTVxIYtPJ0eS6pnAnkTAaJgUJh1JhZS4ekzgswMfEYXOwpMaD5eiqPJLpuxmZFnXnBZlnQ1JMXsw==", + "dev": true, + "dependencies": { + "ethers": "4.0.0-beta.3", + "underscore": "1.9.1", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-abi/node_modules/@types/node": { + "version": "10.17.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", + "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "dev": true + }, + "node_modules/web3-eth-abi/node_modules/elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "dev": true, + "dependencies": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/web3-eth-abi/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-abi/node_modules/eth-lib/node_modules/elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/web3-eth-abi/node_modules/ethers": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", + "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", + "dev": true, + "dependencies": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.3", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/web3-eth-abi/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web3-eth-abi/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/web3-eth-abi/node_modules/scrypt-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", + "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", + "dev": true + }, + "node_modules/web3-eth-abi/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", + "dev": true + }, + "node_modules/web3-eth-abi/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", + "dev": true + }, + "node_modules/web3-eth-abi/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-abi/node_modules/web3-utils/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth-accounts": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.2.tgz", + "integrity": "sha512-KzHOEyXOEZ13ZOkWN3skZKqSo5f4Z1ogPFNn9uZbKCz+kSp+gCAEKxyfbOsB/JMAp5h7o7pb6eYsPCUBJmFFiA==", + "dev": true, + "dependencies": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "ethereumjs-common": "^1.3.2", + "ethereumjs-tx": "^2.1.1", + "scrypt-shim": "github:web3-js/scrypt-shim", + "underscore": "1.9.1", + "uuid": "3.3.2", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-accounts/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-accounts/node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/web3-eth-accounts/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-accounts/node_modules/web3-utils/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth-contract": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.2.tgz", + "integrity": "sha512-EKT2yVFws3FEdotDQoNsXTYL798+ogJqR2//CaGwx3p0/RvQIgfzEwp8nbgA6dMxCsn9KOQi7OtklzpnJMkjtA==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.4", + "underscore": "1.9.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-promievent": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-eth-abi": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-contract/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth-contract/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-contract/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-ens": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.2.tgz", + "integrity": "sha512-CFjkr2HnuyMoMFBoNUWojyguD4Ef+NkyovcnUc/iAb9GP4LHohKrODG4pl76R5u61TkJGobC2ij6TyibtsyVYg==", + "dev": true, + "dependencies": { + "eth-ens-namehash": "2.0.8", + "underscore": "1.9.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-promievent": "1.2.2", + "web3-eth-abi": "1.2.2", + "web3-eth-contract": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-ens/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth-ens/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-ens/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-iban": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.2.tgz", + "integrity": "sha512-gxKXBoUhaTFHr0vJB/5sd4i8ejF/7gIsbM/VvemHT3tF5smnmY6hcwSMmn7sl5Gs+83XVb/BngnnGkf+I/rsrQ==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-iban/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth-iban/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-iban/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-personal": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.2.tgz", + "integrity": "sha512-4w+GLvTlFqW3+q4xDUXvCEMU7kRZ+xm/iJC8gm1Li1nXxwwFbs+Y+KBK6ZYtoN1qqAnHR+plYpIoVo27ixI5Rg==", + "dev": true, + "dependencies": { + "@types/node": "^12.6.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-net": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-personal/node_modules/@types/node": { + "version": "12.19.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", + "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", + "dev": true + }, + "node_modules/web3-eth-personal/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth-personal/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-personal/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-net": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.2.tgz", + "integrity": "sha512-K07j2DXq0x4UOJgae65rWZKraOznhk8v5EGSTdFqASTx7vWE/m+NqBijBYGEsQY1lSMlVaAY9UEQlcXK5HzXTw==", + "dev": true, + "dependencies": { + "web3-core": "1.2.2", + "web3-core-method": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-net/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-net/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-net/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-http": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.2.tgz", + "integrity": "sha512-BNZ7Hguy3eBszsarH5gqr9SIZNvqk9eKwqwmGH1LQS1FL3NdoOn7tgPPdddrXec4fL94CwgNk4rCU+OjjZRNDg==", + "dev": true, + "dependencies": { + "web3-core-helpers": "1.2.2", + "xhr2-cookies": "1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-ipc": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.2.tgz", + "integrity": "sha512-t97w3zi5Kn/LEWGA6D9qxoO0LBOG+lK2FjlEdCwDQatffB/+vYrzZ/CLYVQSoyFZAlsDoBasVoYSWZK1n39aHA==", + "dev": true, + "dependencies": { + "oboe": "2.1.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-ws": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.2.tgz", + "integrity": "sha512-Wb1mrWTGMTXOpJkL0yGvL/WYLt8fUIXx8k/l52QB2IiKzvyd42dTWn4+j8IKXGSYYzOm7NMqv6nhA5VDk12VfA==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2", + "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-shh": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.2.tgz", + "integrity": "sha512-og258NPhlBn8yYrDWjoWBBb6zo1OlBgoWGT+LL5/LPqRbjPe09hlOYHgscAAr9zZGtohTOty7RrxYw6Z6oDWCg==", + "dev": true, + "dependencies": { + "web3-core": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-net": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.0.tgz", + "integrity": "sha512-2mS5axFCbkhicmoDRuJeuo0TVGQDgC2sPi/5dblfVC+PMtX0efrb8Xlttv/eGkq7X4E83Pds34FH98TP2WOUZA==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3/node_modules/@types/node": { + "version": "12.19.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", + "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", + "dev": true + }, + "node_modules/web3/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3/node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3/node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3/node_modules/ethers": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", + "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", + "dev": true, + "dependencies": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.3", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/web3/node_modules/ethers/node_modules/@types/node": { + "version": "10.17.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", + "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "dev": true + }, + "node_modules/web3/node_modules/ethers/node_modules/elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "dev": true, + "dependencies": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/web3/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/web3/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web3/node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/web3/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/web3/node_modules/normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3/node_modules/scrypt-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", + "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", + "dev": true + }, + "node_modules/web3/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", + "dev": true + }, + "node_modules/web3/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", + "dev": true + }, + "node_modules/web3/node_modules/web3-bzz": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.6.tgz", + "integrity": "sha512-9NiHLlxdI1XeFtbPJAmi2jnnIHVF+GNy517wvOS72P7ZfuJTPwZaSNXfT01vWgPPE9R96/uAHDWHOg+T4WaDQQ==", + "dev": true, + "dependencies": { + "@types/node": "^10.12.18", + "got": "9.6.0", + "swarm-js": "0.1.39", + "underscore": "1.9.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-bzz/node_modules/@types/node": { + "version": "10.17.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", + "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "dev": true + }, + "node_modules/web3/node_modules/web3-core": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.6.tgz", + "integrity": "sha512-y/QNBFtr5cIR8vxebnotbjWJpOnO8LDYEAzZjeRRUJh2ijmhjoYk7dSNx9ExgC0UCfNFRoNCa9dGRu/GAxwRlw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.4", + "@types/node": "^12.6.1", + "web3-core-helpers": "1.2.6", + "web3-core-method": "1.2.6", + "web3-core-requestmanager": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-core-helpers": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.6.tgz", + "integrity": "sha512-gYKWmC2HmO7RcDzpo4L1K8EIoy5L8iubNDuTC6q69UxczwqKF/Io0kbK/1Z10Av++NlzOSiuyGp2gc4t4UOsDw==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-eth-iban": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-core-method": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.6.tgz", + "integrity": "sha512-r2dzyPEonqkBg7Mugq5dknhV5PGaZTHBZlS/C+aMxNyQs3T3eaAsCTqlQDitwNUh/sUcYPEGF0Vo7ahYK4k91g==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.6", + "web3-core-promievent": "1.2.6", + "web3-core-subscriptions": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-core-promievent": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.6.tgz", + "integrity": "sha512-km72kJef/qtQNiSjDJJVHIZvoVOm6ytW3FCYnOcCs7RIkviAb5JYlPiye0o4pJOLzCXYID7DK7Q9bhY8qWb1lw==", + "dev": true, + "dependencies": { + "any-promise": "1.3.0", + "eventemitter3": "3.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-core-requestmanager": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.6.tgz", + "integrity": "sha512-QU2cbsj9Dm0r6om40oSwk8Oqbp3wTa08tXuMpSmeOTkGZ3EMHJ1/4LiJ8shwg1AvPMrKVU0Nri6+uBNCdReZ+g==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.6", + "web3-providers-http": "1.2.6", + "web3-providers-ipc": "1.2.6", + "web3-providers-ws": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-core-subscriptions": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.6.tgz", + "integrity": "sha512-M0PzRrP2Ct13x3wPulFtc5kENH4UtnPxO9YxkfQlX2WRKENWjt4Rfq+BCVGYEk3rTutDfWrjfzjmqMRvXqEY5Q==", + "dev": true, + "dependencies": { + "eventemitter3": "3.1.2", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.6.tgz", + "integrity": "sha512-ROWlDPzh4QX6tlGGGlAK6X4kA2n0/cNj/4kb0nNVWkRouGmYO0R8k6s47YxYHvGiXt0s0++FUUv5vAbWovtUQw==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core": "1.2.6", + "web3-core-helpers": "1.2.6", + "web3-core-method": "1.2.6", + "web3-core-subscriptions": "1.2.6", + "web3-eth-abi": "1.2.6", + "web3-eth-accounts": "1.2.6", + "web3-eth-contract": "1.2.6", + "web3-eth-ens": "1.2.6", + "web3-eth-iban": "1.2.6", + "web3-eth-personal": "1.2.6", + "web3-net": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth-abi": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.6.tgz", + "integrity": "sha512-w9GAyyikn8nSifSDZxAvU9fxtQSX+W2xQWMmrtTXmBGCaE4/ywKOSPAO78gq8AoU4Wq5yqVGKZLLbfpt7/sHlA==", + "dev": true, + "dependencies": { + "ethers": "4.0.0-beta.3", + "underscore": "1.9.1", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth-accounts": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.6.tgz", + "integrity": "sha512-cDVtonHRgzqi/ZHOOf8kfCQWFEipcfQNAMzXIaKZwc0UUD9mgSI5oJrN45a89Ze+E6Lz9m77cDG5Ax9zscSkcw==", + "dev": true, + "dependencies": { + "@web3-js/scrypt-shim": "^0.1.0", + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "^0.2.8", + "ethereumjs-common": "^1.3.2", + "ethereumjs-tx": "^2.1.1", + "underscore": "1.9.1", + "uuid": "3.3.2", + "web3-core": "1.2.6", + "web3-core-helpers": "1.2.6", + "web3-core-method": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth-accounts/node_modules/eth-lib": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3/node_modules/web3-eth-accounts/node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/web3/node_modules/web3-eth-contract": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.6.tgz", + "integrity": "sha512-ak4xbHIhWgsbdPCkSN+HnQc1SH4c856y7Ly+S57J/DQVzhFZemK5HvWdpwadJrQTcHET3ZeId1vq3kmW7UYodw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.4", + "underscore": "1.9.1", + "web3-core": "1.2.6", + "web3-core-helpers": "1.2.6", + "web3-core-method": "1.2.6", + "web3-core-promievent": "1.2.6", + "web3-core-subscriptions": "1.2.6", + "web3-eth-abi": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth-ens": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.6.tgz", + "integrity": "sha512-8UEqt6fqR/dji/jBGPFAyBs16OJjwi0t2dPWXPyGXmty/fH+osnXwWXE4HRUyj4xuafiM5P1YkXMsPhKEadjiw==", + "dev": true, + "dependencies": { + "eth-ens-namehash": "2.0.8", + "underscore": "1.9.1", + "web3-core": "1.2.6", + "web3-core-helpers": "1.2.6", + "web3-core-promievent": "1.2.6", + "web3-eth-abi": "1.2.6", + "web3-eth-contract": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth-iban": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.6.tgz", + "integrity": "sha512-TPMc3BW9Iso7H+9w+ytbqHK9wgOmtocyCD3PaAe5Eie50KQ/j7ThA60dGJnxItVo6yyRv5pZAYxPVob9x/fJlg==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth-personal": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.6.tgz", + "integrity": "sha512-T2NUkh1plY8d7wePXSoHnaiKOd8dLNFaQfgBl9JHU6S7IJrG9jnYD9bVxLEgRUfHs9gKf9tQpDf7AcPFdq/A8g==", + "dev": true, + "dependencies": { + "@types/node": "^12.6.1", + "web3-core": "1.2.6", + "web3-core-helpers": "1.2.6", + "web3-core-method": "1.2.6", + "web3-net": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-net": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.6.tgz", + "integrity": "sha512-hsNHAPddrhgjWLmbESW0KxJi2GnthPcow0Sqpnf4oB6+/+ZnQHU9OsIyHb83bnC1OmunrK2vf9Ye2mLPdFIu3A==", + "dev": true, + "dependencies": { + "web3-core": "1.2.6", + "web3-core-method": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-providers-http": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.6.tgz", + "integrity": "sha512-2+SaFCspb5f82QKuHB3nEPQOF9iSWxRf7c18fHtmnLNVkfG9SwLN1zh67bYn3tZGUdOI3gj8aX4Uhfpwx9Ezpw==", + "dev": true, + "dependencies": { + "web3-core-helpers": "1.2.6", + "xhr2-cookies": "1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-providers-ipc": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.6.tgz", + "integrity": "sha512-b0Es+/GTZyk5FG3SgUDW+2/mBwJAXWt5LuppODptiOas8bB2khLjG6+Gm1K4uwOb+1NJGPt5mZZ8Wi7vibtQ+A==", + "dev": true, + "dependencies": { + "oboe": "2.1.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-providers-ws": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.6.tgz", + "integrity": "sha512-20waSYX+gb5M5yKhug5FIwxBBvkKzlJH7sK6XEgdOx6BZ9YYamLmvg9wcRVtnSZO8hV/3cWenO/tRtTrHVvIgQ==", + "dev": true, + "dependencies": { + "@web3-js/websocket": "^1.0.29", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-shh": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.6.tgz", + "integrity": "sha512-rouWyOOM6YMbLQd65grpj8BBezQfgNeRRX+cGyW4xsn6Xgu+B73Zvr6OtA/ftJwwa9bqHGpnLrrLMeWyy4YLUw==", + "dev": true, + "dependencies": { + "web3-core": "1.2.6", + "web3-core-method": "1.2.6", + "web3-core-subscriptions": "1.2.6", + "web3-net": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-utils": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.6.tgz", + "integrity": "sha512-8/HnqG/l7dGmKMgEL9JeKPTtjScxOePTzopv5aaKFExPfaBrYRkgoMqhoowCiAl/s16QaTn4DoIF1QC4YsT7Mg==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/websocket": { + "resolved": "git+ssh://git@github.com/web3-js/WebSocket-Node.git#ef5ea2f41daf4a2113b80c9223df884b4d56c400", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "nan": "^2.14.0", + "typedarray-to-buffer": "^3.1.5", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/websocket/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/websocket/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", + "dev": true, + "bin": { + "window-size": "cli.js" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", + "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==", + "dev": true, + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/xhr": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", + "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "dev": true, + "dependencies": { + "global": "~4.3.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/xhr-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", + "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "dev": true, + "dependencies": { + "buffer-to-arraybuffer": "^0.0.5", + "object-assign": "^4.1.1", + "query-string": "^5.0.1", + "simple-get": "^2.7.0", + "timed-out": "^4.0.1", + "url-set-query": "^1.0.0", + "xhr": "^2.0.4" + } + }, + "node_modules/xhr-request-promise": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz", + "integrity": "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==", + "dev": true, + "dependencies": { + "xhr-request": "^1.1.0" + } + }, + "node_modules/xhr/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/xhr2-cookies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", + "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", + "dev": true, + "dependencies": { + "cookiejar": "^2.1.1" + } + }, + "node_modules/xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "node_modules/yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", + "dev": true, + "engines": { + "node": ">=0.10.32" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "dependencies": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + } + }, "dependencies": { "@babel/code-frame": { "version": "7.10.4", @@ -5583,13 +30913,11 @@ "dependencies": { "ansi-regex": { "version": "4.1.0", - "resolved": false, "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "ansi-styles": { "version": "3.2.1", - "resolved": false, "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { @@ -5598,7 +30926,6 @@ }, "bindings": { "version": "1.5.0", - "resolved": false, "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, "requires": { @@ -5607,7 +30934,6 @@ }, "bip66": { "version": "1.1.5", - "resolved": false, "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", "dev": true, "requires": { @@ -5616,19 +30942,16 @@ }, "bn.js": { "version": "4.11.8", - "resolved": false, "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, "brorand": { "version": "1.1.0", - "resolved": false, "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, "browserify-aes": { "version": "1.2.0", - "resolved": false, "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -5642,25 +30965,21 @@ }, "buffer-from": { "version": "1.1.1", - "resolved": false, "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, "buffer-xor": { "version": "1.0.3", - "resolved": false, "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, "camelcase": { "version": "5.3.1", - "resolved": false, "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "cipher-base": { "version": "1.0.4", - "resolved": false, "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { @@ -5670,7 +30989,6 @@ }, "cliui": { "version": "5.0.0", - "resolved": false, "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { @@ -5681,7 +30999,6 @@ }, "color-convert": { "version": "1.9.3", - "resolved": false, "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { @@ -5690,13 +31007,11 @@ }, "color-name": { "version": "1.1.3", - "resolved": false, "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "create-hash": { "version": "1.2.0", - "resolved": false, "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { @@ -5709,7 +31024,6 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": false, "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { @@ -5723,7 +31037,6 @@ }, "cross-spawn": { "version": "6.0.5", - "resolved": false, "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { @@ -5736,13 +31049,11 @@ }, "decamelize": { "version": "1.2.0", - "resolved": false, "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "drbg.js": { "version": "1.0.1", - "resolved": false, "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", "dev": true, "requires": { @@ -5753,7 +31064,6 @@ }, "elliptic": { "version": "6.5.0", - "resolved": false, "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", "dev": true, "requires": { @@ -5768,13 +31078,11 @@ }, "emoji-regex": { "version": "7.0.3", - "resolved": false, "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "end-of-stream": { "version": "1.4.1", - "resolved": false, "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { @@ -5783,7 +31091,6 @@ }, "ethereumjs-util": { "version": "6.1.0", - "resolved": false, "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", "dev": true, "requires": { @@ -5798,7 +31105,6 @@ }, "ethjs-util": { "version": "0.1.6", - "resolved": false, "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", "dev": true, "requires": { @@ -5808,7 +31114,6 @@ }, "evp_bytestokey": { "version": "1.0.3", - "resolved": false, "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, "requires": { @@ -5818,7 +31123,6 @@ }, "execa": { "version": "1.0.0", - "resolved": false, "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { @@ -5833,13 +31137,11 @@ }, "file-uri-to-path": { "version": "1.0.0", - "resolved": false, "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "dev": true }, "find-up": { "version": "3.0.0", - "resolved": false, "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { @@ -5848,13 +31150,11 @@ }, "get-caller-file": { "version": "2.0.5", - "resolved": false, "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-stream": { "version": "4.1.0", - "resolved": false, "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "requires": { @@ -5863,7 +31163,6 @@ }, "hash-base": { "version": "3.0.4", - "resolved": false, "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, "requires": { @@ -5873,7 +31172,6 @@ }, "hash.js": { "version": "1.1.7", - "resolved": false, "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, "requires": { @@ -5883,7 +31181,6 @@ }, "hmac-drbg": { "version": "1.0.1", - "resolved": false, "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { @@ -5894,43 +31191,36 @@ }, "inherits": { "version": "2.0.4", - "resolved": false, "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "invert-kv": { "version": "2.0.0", - "resolved": false, "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", - "resolved": false, "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "is-hex-prefixed": { "version": "1.0.0", - "resolved": false, "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", "dev": true }, "is-stream": { "version": "1.1.0", - "resolved": false, "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, "isexe": { "version": "2.0.0", - "resolved": false, "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "keccak": { "version": "1.4.0", - "resolved": false, "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", "dev": true, "requires": { @@ -5942,7 +31232,6 @@ }, "lcid": { "version": "2.0.0", - "resolved": false, "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { @@ -5951,7 +31240,6 @@ }, "locate-path": { "version": "3.0.0", - "resolved": false, "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { @@ -5961,7 +31249,6 @@ }, "map-age-cleaner": { "version": "0.1.3", - "resolved": false, "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", "dev": true, "requires": { @@ -5970,7 +31257,6 @@ }, "md5.js": { "version": "1.3.5", - "resolved": false, "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, "requires": { @@ -5981,7 +31267,6 @@ }, "mem": { "version": "4.3.0", - "resolved": false, "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, "requires": { @@ -5992,37 +31277,31 @@ }, "mimic-fn": { "version": "2.1.0", - "resolved": false, "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "minimalistic-assert": { "version": "1.0.1", - "resolved": false, "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, "minimalistic-crypto-utils": { "version": "1.0.1", - "resolved": false, "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", "dev": true }, "nan": { "version": "2.14.0", - "resolved": false, "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "dev": true }, "nice-try": { "version": "1.0.5", - "resolved": false, "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "npm-run-path": { "version": "2.0.2", - "resolved": false, "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { @@ -6031,7 +31310,6 @@ }, "once": { "version": "1.4.0", - "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { @@ -6040,7 +31318,6 @@ }, "os-locale": { "version": "3.1.0", - "resolved": false, "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { @@ -6051,25 +31328,21 @@ }, "p-defer": { "version": "1.0.0", - "resolved": false, "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", "dev": true }, "p-finally": { "version": "1.0.0", - "resolved": false, "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, "p-is-promise": { "version": "2.1.0", - "resolved": false, "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", "dev": true }, "p-limit": { "version": "2.2.0", - "resolved": false, "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { @@ -6078,7 +31351,6 @@ }, "p-locate": { "version": "3.0.0", - "resolved": false, "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { @@ -6087,25 +31359,21 @@ }, "p-try": { "version": "2.2.0", - "resolved": false, "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "path-exists": { "version": "3.0.0", - "resolved": false, "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, "path-key": { "version": "2.0.1", - "resolved": false, "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "pump": { "version": "3.0.0", - "resolved": false, "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { @@ -6115,19 +31383,16 @@ }, "require-directory": { "version": "2.1.1", - "resolved": false, "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { "version": "2.0.0", - "resolved": false, "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "ripemd160": { "version": "2.0.2", - "resolved": false, "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { @@ -6137,7 +31402,6 @@ }, "rlp": { "version": "2.2.3", - "resolved": false, "integrity": "sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==", "dev": true, "requires": { @@ -6147,13 +31411,11 @@ }, "safe-buffer": { "version": "5.2.0", - "resolved": false, "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", "dev": true }, "secp256k1": { "version": "3.7.1", - "resolved": false, "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", "dev": true, "requires": { @@ -6169,19 +31431,16 @@ }, "semver": { "version": "5.7.0", - "resolved": false, "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "sha.js": { "version": "2.4.11", - "resolved": false, "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -6191,7 +31450,6 @@ }, "shebang-command": { "version": "1.2.0", - "resolved": false, "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { @@ -6200,25 +31458,21 @@ }, "shebang-regex": { "version": "1.0.0", - "resolved": false, "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, "source-map": { "version": "0.6.1", - "resolved": false, "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "source-map-support": { "version": "0.5.12", - "resolved": false, "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", "dev": true, "requires": { @@ -6228,7 +31482,6 @@ }, "string-width": { "version": "3.1.0", - "resolved": false, "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { @@ -6239,7 +31492,6 @@ }, "strip-ansi": { "version": "5.2.0", - "resolved": false, "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { @@ -6248,13 +31500,11 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": false, "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "strip-hex-prefix": { "version": "1.0.0", - "resolved": false, "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", "dev": true, "requires": { @@ -6263,7 +31513,6 @@ }, "which": { "version": "1.3.1", - "resolved": false, "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { @@ -6272,13 +31521,11 @@ }, "which-module": { "version": "2.0.0", - "resolved": false, "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "wrap-ansi": { "version": "5.1.0", - "resolved": false, "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { @@ -6289,19 +31536,16 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "y18n": { "version": "4.0.0", - "resolved": false, "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yargs": { "version": "13.2.4", - "resolved": false, "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", "dev": true, "requires": { @@ -6320,7 +31564,6 @@ }, "yargs-parser": { "version": "13.1.1", - "resolved": false, "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { @@ -13600,6 +38843,23 @@ "dev": true, "optional": true }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, "string.prototype.trim": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.2.tgz", @@ -13652,23 +38912,6 @@ "es-abstract": "^1.17.5" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, "strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -14609,8 +39852,8 @@ }, "ethereumjs-abi": { "version": "git+https://git@github.com/ethereumjs/ethereumjs-abi.git#1ce6a1d64235fabe2aaf827fd606def55693508f", - "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "dev": true, + "from": "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" @@ -16761,6 +42004,12 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, + "lru_map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", + "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=", + "dev": true + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -16770,12 +42019,6 @@ "yallist": "^3.0.2" } }, - "lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=", - "dev": true - }, "ltgt": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", @@ -18899,9 +44142,9 @@ "dev": true }, "scrypt-shim": { - "version": "github:web3-js/scrypt-shim#aafdadda13e660e25e1c525d1f5b2443f5eb1ebb", - "from": "github:web3-js/scrypt-shim", + "version": "git+ssh://git@github.com/web3-js/scrypt-shim.git#aafdadda13e660e25e1c525d1f5b2443f5eb1ebb", "dev": true, + "from": "scrypt-shim@github:web3-js/scrypt-shim", "requires": { "scryptsy": "^2.1.0", "semver": "^6.3.0" @@ -19605,6 +44848,15 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "dev": true }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -19691,15 +44943,6 @@ } } }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -21965,9 +47208,9 @@ } }, "websocket": { - "version": "github:web3-js/WebSocket-Node#ef5ea2f41daf4a2113b80c9223df884b4d56c400", - "from": "github:web3-js/WebSocket-Node#polyfill/globalThis", + "version": "git+ssh://git@github.com/web3-js/WebSocket-Node.git#ef5ea2f41daf4a2113b80c9223df884b4d56c400", "dev": true, + "from": "websocket@github:web3-js/WebSocket-Node#polyfill/globalThis", "requires": { "debug": "^2.2.0", "es5-ext": "^0.10.50", diff --git a/tasks/deployments/deploy-wethGateWay.ts b/tasks/deployments/deploy-wethGateWay.ts deleted file mode 100644 index 83611efc..00000000 --- a/tasks/deployments/deploy-wethGateWay.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { task } from 'hardhat/config'; - -import { deployWETHGateway } from '../../helpers/contracts-deployments'; - -const CONTRACT_NAME = 'WETHGateway'; - -task(`deploy-${CONTRACT_NAME}`, `Deploys the ${CONTRACT_NAME} contract`) - .addParam('weth', 'Address of the weth token') - .addFlag('verify', `Verify ${CONTRACT_NAME} contract via Etherscan API.`) - .setAction(async ({ weth, verify }, localBRE) => { - await localBRE.run('set-DRE'); - - if (!localBRE.network.config.chainId) { - throw new Error('INVALID_CHAIN_ID'); - } - - const wethGateWay = await deployWETHGateway([weth], verify); - console.log(`${CONTRACT_NAME}.address`, wethGateWay.address); - - console.log(`\tFinished ${CONTRACT_NAME} deployment`); - }); diff --git a/tasks/full/5-deploy-wethGateWay.ts b/tasks/full/5-deploy-wethGateWay.ts new file mode 100644 index 00000000..279580ef --- /dev/null +++ b/tasks/full/5-deploy-wethGateWay.ts @@ -0,0 +1,32 @@ +import { task } from 'hardhat/config'; +import { AaveConfig } from '../../markets/aave/index'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { loadPoolConfig, ConfigNames } from '../../helpers/configuration'; +import { deployWETHGateway } from '../../helpers/contracts-deployments'; +import { DRE } from '../../helpers/misc-utils'; +import { eEthereumNetwork } from '../../helpers/types'; + +const CONTRACT_NAME = 'WETHGateway'; + +task(`full-deploy-weth-gateway`, `Deploys the ${CONTRACT_NAME} contract`) + .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) + .addFlag('verify', `Verify ${CONTRACT_NAME} contract via Etherscan API.`) + .setAction(async ({ verify, pool }, localBRE) => { + await localBRE.run('set-DRE'); + const network = localBRE.network.name; + const Weth = AaveConfig.ReserveAssets[DRE.network.name].WETH; + const poolConfig = loadPoolConfig(pool); + const { WethGateway } = poolConfig; + + if (!localBRE.network.config.chainId) { + throw new Error('INVALID_CHAIN_ID'); + } + let gateWay = getParamPerNetwork(WethGateway, network); + if (gateWay === '') { + const wethGateWay = await deployWETHGateway([Weth], verify); + console.log(`${CONTRACT_NAME}.address`, wethGateWay.address); + console.log(`\tFinished ${CONTRACT_NAME} deployment`); + } else { + console.log(`Weth gateway already deployed. Address: ${gateWay}`); + } + }); diff --git a/tasks/full/5_initialize.ts b/tasks/full/6-initialize.ts similarity index 93% rename from tasks/full/5_initialize.ts rename to tasks/full/6-initialize.ts index 2e92ad90..1b949241 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/6-initialize.ts @@ -12,6 +12,7 @@ import { getWethAddress, getTreasuryAddress, } from '../../helpers/configuration'; +import { getWETHGateway } from '../../helpers/contracts-getters'; import { eEthereumNetwork, ICommonConfiguration } from '../../helpers/types'; import { waitForTx } from '../../helpers/misc-utils'; import { initReservesByHelper, configureReservesByHelper } from '../../helpers/init-helpers'; @@ -86,7 +87,10 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const lendingPoolAddress = await addressesProvider.getLendingPool(); - const gateWay = await getParamPerNetwork(WethGateway, network); + let gateWay = getParamPerNetwork(WethGateway, network); + if (gateWay == '') { + gateWay = (await getWETHGateway()).address; + } await authorizeWETHGateway(gateWay, lendingPoolAddress); } catch (err) { console.error(err); diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index 96bcbbb8..ccf71f3a 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -29,15 +29,18 @@ task('aave:mainnet', 'Deploy development enviroment') console.log('4. Deploy Data Provider'); await DRE.run('full:data-provider', { pool: POOL_NAME }); - console.log('5. Initialize lending pool'); + console.log('5. Deploy weth Gethway provider'); + 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 }); if (verify) { printContracts(); - console.log('4. Veryfing contracts'); + console.log('7. Veryfing contracts'); await DRE.run('verify:general', { all: true, pool: POOL_NAME }); - console.log('5. Veryfing aTokens and debtTokens'); + console.log('8. Veryfing aTokens and debtTokens'); await DRE.run('verify:tokens', { pool: POOL_NAME }); } diff --git a/tasks/verifications/1_general.ts b/tasks/verifications/1_general.ts index 6e42e483..89a54d0d 100644 --- a/tasks/verifications/1_general.ts +++ b/tasks/verifications/1_general.ts @@ -89,10 +89,7 @@ task('verify:general', 'Deploy oracles for dev enviroment') // WETHGateway console.log('\n- Verifying WETHGateway...\n'); - await verifyContract(wethGateway.address, [ - await getWethAddress(poolConfig), - lendingPoolProxy.address, - ]); + await verifyContract(wethGateway.address, [await getWethAddress(poolConfig)]); } // Lending Pool proxy console.log('\n- Verifying Lending Pool Proxy...\n'); From ed93b2730d373591bbc803ceb4c8fc593d713085 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 22 Feb 2021 09:06:51 -0500 Subject: [PATCH 134/219] Updated most recent registry & owner addresses --- markets/matic/commons.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index 83790bcb..0bc92154 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -91,7 +91,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', [eEthereumNetwork.mumbai]: '0x569859d41499B4dDC28bfaA43915051FF0A38a6F', // TEMP - [eEthereumNetwork.matic]: '0x3E7803614113F4199bE15b9dC915FA2f4EDE902B', // TEMP + [eEthereumNetwork.matic]: '0x28334e4791860a0c1eCF89a62B973ba04a5d643F', // TEMP }, ProviderRegistryOwner: { [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', @@ -102,7 +102,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', [eEthereumNetwork.mumbai]: '0x18d9bA2baEfBdE0FF137C4ad031427EF205f1Fd9', // TEMP - [eEthereumNetwork.matic]: '0x18d9bA2baEfBdE0FF137C4ad031427EF205f1Fd9', // TEMP + [eEthereumNetwork.matic]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', // TEMP }, LendingRateOracle: { [eEthereumNetwork.coverage]: '', From f8d8f402324fb150dc21b1c3328f67b0149e5452 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 22 Feb 2021 09:57:48 -0500 Subject: [PATCH 135/219] Slight fixed for fork deployment --- tasks/full/5-deploy-wethGateWay.ts | 4 ++-- tasks/migrations/aave.mainnet.ts | 2 +- tasks/migrations/lp.mainnet.ts | 9 ++++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tasks/full/5-deploy-wethGateWay.ts b/tasks/full/5-deploy-wethGateWay.ts index 279580ef..12c97a15 100644 --- a/tasks/full/5-deploy-wethGateWay.ts +++ b/tasks/full/5-deploy-wethGateWay.ts @@ -1,7 +1,7 @@ import { task } from 'hardhat/config'; import { AaveConfig } from '../../markets/aave/index'; import { getParamPerNetwork } from '../../helpers/contracts-helpers'; -import { loadPoolConfig, ConfigNames } from '../../helpers/configuration'; +import { loadPoolConfig, ConfigNames, getWethAddress } from '../../helpers/configuration'; import { deployWETHGateway } from '../../helpers/contracts-deployments'; import { DRE } from '../../helpers/misc-utils'; import { eEthereumNetwork } from '../../helpers/types'; @@ -14,8 +14,8 @@ task(`full-deploy-weth-gateway`, `Deploys the ${CONTRACT_NAME} contract`) .setAction(async ({ verify, pool }, localBRE) => { await localBRE.run('set-DRE'); const network = localBRE.network.name; - const Weth = AaveConfig.ReserveAssets[DRE.network.name].WETH; const poolConfig = loadPoolConfig(pool); + const Weth = await getWethAddress(poolConfig); const { WethGateway } = poolConfig; if (!localBRE.network.config.chainId) { diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index ccf71f3a..fe05938d 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -29,7 +29,7 @@ task('aave:mainnet', 'Deploy development enviroment') console.log('4. Deploy Data Provider'); await DRE.run('full:data-provider', { pool: POOL_NAME }); - console.log('5. Deploy weth Gethway provider'); + console.log('5. Deploy WETH Gateway'); await DRE.run('full-deploy-weth-gateway', { pool: POOL_NAME }); console.log('6. Initialize lending pool'); diff --git a/tasks/migrations/lp.mainnet.ts b/tasks/migrations/lp.mainnet.ts index 912f48b4..4faea738 100644 --- a/tasks/migrations/lp.mainnet.ts +++ b/tasks/migrations/lp.mainnet.ts @@ -29,15 +29,18 @@ task('lp:mainnet', 'Deploy development enviroment') console.log('4. Deploy Data Provider'); await DRE.run('full:data-provider', { pool: POOL_NAME }); - console.log('5. Initialize lending pool'); + 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 }); if (verify) { printContracts(); - console.log('4. Veryfing contracts'); + console.log('7. Veryfing contracts'); await DRE.run('verify:general', { all: true, pool: POOL_NAME }); - console.log('5. Veryfing aTokens and debtTokens'); + console.log('8. Veryfing aTokens and debtTokens'); await DRE.run('verify:tokens', { pool: POOL_NAME }); } From a7e1cad87b878e1bfd3a2dd6c03ede4542d75621 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 22 Feb 2021 12:30:26 +0100 Subject: [PATCH 136/219] Updated Weth gateway contract --- contracts/misc/WETHGateway.sol | 65 ++++++++++++---------- contracts/misc/interfaces/IWETHGateway.sol | 14 ++++- 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/contracts/misc/WETHGateway.sol b/contracts/misc/WETHGateway.sol index b90c9bbf..e2ef175c 100644 --- a/contracts/misc/WETHGateway.sol +++ b/contracts/misc/WETHGateway.sol @@ -18,20 +18,21 @@ contract WETHGateway is IWETHGateway, Ownable { using UserConfiguration for DataTypes.UserConfigurationMap; IWETH internal immutable WETH; - ILendingPool internal immutable POOL; - IAToken internal immutable aWETH; /** * @dev Sets the WETH address and the LendingPoolAddressesProvider address. Infinite approves lending pool. * @param weth Address of the Wrapped Ether contract - * @param pool Address of the LendingPool contract **/ - constructor(address weth, address pool) public { - ILendingPool poolInstance = ILendingPool(pool); + constructor(address weth) public { WETH = IWETH(weth); - POOL = poolInstance; - aWETH = IAToken(poolInstance.getReserveData(weth).aTokenAddress); - IWETH(weth).approve(pool, uint256(-1)); + } + + function authorizeLendingPool(address lendingPool) external onlyOwner { + require( + ILendingPool(lendingPool).getReserveData(address(WETH)).aTokenAddress != address(0), + 'AWETH_NOT_SETUP' + ); + WETH.approve(lendingPool, uint256(-1)); } /** @@ -40,9 +41,13 @@ contract WETHGateway is IWETHGateway, Ownable { * @param onBehalfOf address of the user who will receive the aTokens representing the deposit * @param referralCode integrators are assigned a referral code and can potentially receive rewards. **/ - function depositETH(address onBehalfOf, uint16 referralCode) external payable override { + function depositETH( + address lendingPool, + address onBehalfOf, + uint16 referralCode + ) external payable override { WETH.deposit{value: msg.value}(); - POOL.deposit(address(WETH), msg.value, onBehalfOf, referralCode); + ILendingPool(lendingPool).deposit(address(WETH), msg.value, onBehalfOf, referralCode); } /** @@ -50,7 +55,12 @@ contract WETHGateway is IWETHGateway, Ownable { * @param amount amount of aWETH to withdraw and receive native ETH * @param to address of the user who will receive native ETH */ - function withdrawETH(uint256 amount, address to) external override { + function withdrawETH( + address lendingPool, + uint256 amount, + address to + ) external override { + IAToken aWETH = IAToken(ILendingPool(lendingPool).getReserveData(address(WETH)).aTokenAddress); uint256 userBalance = aWETH.balanceOf(msg.sender); uint256 amountToWithdraw = amount; @@ -59,7 +69,7 @@ contract WETHGateway is IWETHGateway, Ownable { amountToWithdraw = userBalance; } aWETH.transferFrom(msg.sender, address(this), amountToWithdraw); - POOL.withdraw(address(WETH), amountToWithdraw, address(this)); + ILendingPool(lendingPool).withdraw(address(WETH), amountToWithdraw, address(this)); WETH.withdraw(amountToWithdraw); _safeTransferETH(to, amountToWithdraw); } @@ -71,12 +81,16 @@ contract WETHGateway is IWETHGateway, Ownable { * @param onBehalfOf the address for which msg.sender is repaying */ function repayETH( + address lendingPool, uint256 amount, uint256 rateMode, address onBehalfOf ) external payable override { (uint256 stableDebt, uint256 variableDebt) = - Helpers.getUserCurrentDebtMemory(onBehalfOf, POOL.getReserveData(address(WETH))); + Helpers.getUserCurrentDebtMemory( + onBehalfOf, + ILendingPool(lendingPool).getReserveData(address(WETH)) + ); uint256 paybackAmount = DataTypes.InterestRateMode(rateMode) == DataTypes.InterestRateMode.STABLE @@ -88,7 +102,7 @@ contract WETHGateway is IWETHGateway, Ownable { } require(msg.value >= paybackAmount, 'msg.value is less than repayment amount'); WETH.deposit{value: paybackAmount}(); - POOL.repay(address(WETH), msg.value, rateMode, onBehalfOf); + ILendingPool(lendingPool).repay(address(WETH), msg.value, rateMode, onBehalfOf); // refund remaining dust eth if (msg.value > paybackAmount) _safeTransferETH(msg.sender, msg.value - paybackAmount); @@ -101,11 +115,18 @@ contract WETHGateway is IWETHGateway, Ownable { * @param referralCode integrators are assigned a referral code and can potentially receive rewards */ function borrowETH( + address lendingPool, uint256 amount, uint256 interesRateMode, uint16 referralCode ) external override { - POOL.borrow(address(WETH), amount, interesRateMode, referralCode, msg.sender); + ILendingPool(lendingPool).borrow( + address(WETH), + amount, + interesRateMode, + referralCode, + msg.sender + ); WETH.withdraw(amount); _safeTransferETH(msg.sender, amount); } @@ -152,20 +173,6 @@ contract WETHGateway is IWETHGateway, Ownable { return address(WETH); } - /** - * @dev Get aWETH address used by WETHGateway - */ - function getAWETHAddress() external view returns (address) { - return address(aWETH); - } - - /** - * @dev Get LendingPool address used by WETHGateway - */ - function getLendingPoolAddress() external view returns (address) { - return address(POOL); - } - /** * @dev Only WETH contract is allowed to transfer ETH here. Prevent other addresses to send Ether to this contract. */ diff --git a/contracts/misc/interfaces/IWETHGateway.sol b/contracts/misc/interfaces/IWETHGateway.sol index c06471fb..78d913cd 100644 --- a/contracts/misc/interfaces/IWETHGateway.sol +++ b/contracts/misc/interfaces/IWETHGateway.sol @@ -2,17 +2,27 @@ pragma solidity 0.6.12; interface IWETHGateway { - function depositETH(address onBehalfOf, uint16 referralCode) external payable; + function depositETH( + address lendingPool, + address onBehalfOf, + uint16 referralCode + ) external payable; - function withdrawETH(uint256 amount, address onBehalfOf) external; + function withdrawETH( + address lendingPool, + uint256 amount, + address onBehalfOf + ) external; function repayETH( + address lendingPool, uint256 amount, uint256 rateMode, address onBehalfOf ) external payable; function borrowETH( + address lendingPool, uint256 amount, uint256 interesRateMode, uint16 referralCode From da2ade5d3b43d78e61c41e4316022f1290031690 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 22 Feb 2021 13:23:52 +0100 Subject: [PATCH 137/219] Added Weth gateway contract in config, updated deployment --- contracts/misc/WETHGateway.sol | 8 +- helpers/contracts-deployments.ts | 130 ++++++++------------- helpers/types.ts | 11 +- markets/aave/commons.ts | 9 ++ markets/lp/commons.ts | 9 ++ package.json | 3 +- tasks/deployments/deploy-wethGateWay.ts | 21 ++++ tasks/dev/5_initialize.ts | 9 +- tasks/full/5_initialize.ts | 19 +-- test-suites/test-aave/__setup.spec.ts | 11 +- test-suites/test-aave/weth-gateway.spec.ts | 52 ++++----- test-suites/test-lp/__setup.spec.ts | 4 +- test-suites/test-lp/weth-gateway.spec.ts | 37 +++--- 13 files changed, 162 insertions(+), 161 deletions(-) create mode 100644 tasks/deployments/deploy-wethGateWay.ts diff --git a/contracts/misc/WETHGateway.sol b/contracts/misc/WETHGateway.sol index e2ef175c..336e8de2 100644 --- a/contracts/misc/WETHGateway.sol +++ b/contracts/misc/WETHGateway.sol @@ -28,16 +28,13 @@ contract WETHGateway is IWETHGateway, Ownable { } function authorizeLendingPool(address lendingPool) external onlyOwner { - require( - ILendingPool(lendingPool).getReserveData(address(WETH)).aTokenAddress != address(0), - 'AWETH_NOT_SETUP' - ); WETH.approve(lendingPool, uint256(-1)); } /** * @dev deposits WETH into the reserve, using native ETH. A corresponding amount of the overlying asset (aTokens) * is minted. + * @param lendingPool address of the targeted underlying lending pool * @param onBehalfOf address of the user who will receive the aTokens representing the deposit * @param referralCode integrators are assigned a referral code and can potentially receive rewards. **/ @@ -52,6 +49,7 @@ contract WETHGateway is IWETHGateway, Ownable { /** * @dev withdraws the WETH _reserves of msg.sender. + * @param lendingPool address of the targeted underlying lending pool * @param amount amount of aWETH to withdraw and receive native ETH * @param to address of the user who will receive native ETH */ @@ -76,6 +74,7 @@ contract WETHGateway is IWETHGateway, Ownable { /** * @dev repays a borrow on the WETH reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified). + * @param lendingPool address of the targeted underlying lending pool * @param amount the amount to repay, or uint256(-1) if the user wants to repay everything * @param rateMode the rate mode to repay * @param onBehalfOf the address for which msg.sender is repaying @@ -110,6 +109,7 @@ contract WETHGateway is IWETHGateway, Ownable { /** * @dev borrow WETH, unwraps to ETH and send both the ETH and DebtTokens to msg.sender, via `approveDelegation` and onBehalf argument in `LendingPool.borrow`. + * @param lendingPool address of the targeted underlying lending pool * @param amount the amount of ETH to borrow * @param interesRateMode the interest rate mode * @param referralCode integrators are assigned a referral code and can potentially receive rewards diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index c514ee27..84e12764 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -310,17 +310,10 @@ export const deployStableDebtToken = async ( verify ); - await instance.initialize( - args[0], - args[1], - args[2], - "18", - args[3], - args[4] - ); + await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4]); return instance; -} +}; export const deployVariableDebtToken = async ( args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], @@ -333,31 +326,26 @@ export const deployVariableDebtToken = async ( verify ); - await instance.initialize( - args[0], - args[1], - args[2], - "18", - args[3], - args[4] - ); + await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4]); return instance; -} +}; -export const deployGenericStableDebtToken = async () => withSaveAndVerify( - await new StableDebtTokenFactory(await getFirstSigner()).deploy(), - eContractid.StableDebtToken, - [], - false -); +export const deployGenericStableDebtToken = async () => + withSaveAndVerify( + await new StableDebtTokenFactory(await getFirstSigner()).deploy(), + eContractid.StableDebtToken, + [], + false + ); -export const deployGenericVariableDebtToken = async () => withSaveAndVerify( - await new VariableDebtTokenFactory(await getFirstSigner()).deploy(), - eContractid.VariableDebtToken, - [], - false -); +export const deployGenericVariableDebtToken = async () => + withSaveAndVerify( + await new VariableDebtTokenFactory(await getFirstSigner()).deploy(), + eContractid.VariableDebtToken, + [], + false + ); export const deployGenericAToken = async ( [poolAddress, underlyingAssetAddress, treasuryAddress, incentivesController, name, symbol]: [ @@ -376,23 +364,22 @@ export const deployGenericAToken = async ( [], verify ); - + await instance.initialize( - poolAddress, + poolAddress, treasuryAddress, - underlyingAssetAddress, - incentivesController, - "18", - name, + underlyingAssetAddress, + incentivesController, + '18', + name, symbol ); return instance; }; -export const deployGenericATokenImpl = async ( - verify: boolean -) => withSaveAndVerify( +export const deployGenericATokenImpl = async (verify: boolean) => + withSaveAndVerify( await new ATokenFactory(await getFirstSigner()).deploy(), eContractid.AToken, [], @@ -416,23 +403,22 @@ export const deployDelegationAwareAToken = async ( [], verify ); - + await instance.initialize( pool, treasuryAddress, underlyingAssetAddress, incentivesController, - "18", + '18', name, symbol - ) + ); return instance; }; -export const deployDelegationAwareATokenImpl = async ( - verify: boolean -) => withSaveAndVerify( +export const deployDelegationAwareATokenImpl = async (verify: boolean) => + withSaveAndVerify( await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(), eContractid.DelegationAwareAToken, [], @@ -501,10 +487,7 @@ export const deployATokensAndRatesHelper = async ( verify ); -export const deployWETHGateway = async ( - args: [tEthereumAddress, tEthereumAddress], - verify?: boolean -) => +export const deployWETHGateway = async (args: [tEthereumAddress], verify?: boolean) => withSaveAndVerify( await new WETHGatewayFactory(await getFirstSigner()).deploy(...args), eContractid.WETHGateway, @@ -512,6 +495,14 @@ export const deployWETHGateway = async ( verify ); +export const authorizeWETHGateway = async ( + wethGateWay: tEthereumAddress, + lendingPool: tEthereumAddress +) => + await new WETHGatewayFactory(await getFirstSigner()) + .attach(wethGateWay) + .authorizeLendingPool(lendingPool); + export const deployMockStableDebtToken = async ( args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], verify?: boolean @@ -523,18 +514,10 @@ export const deployMockStableDebtToken = async ( verify ); - await instance.initialize( - args[0], - args[1], - args[2], - "18", - args[3], - args[4] - ); + await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4]); return instance; -} - +}; export const deployWETHMocked = async (verify?: boolean) => withSaveAndVerify( @@ -555,21 +538,13 @@ export const deployMockVariableDebtToken = async ( verify ); - await instance.initialize( - args[0], - args[1], - args[2], - "18", - args[3], - args[4] - ); + await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4]); return instance; -} - +}; export const deployMockAToken = async ( -args: [tEthereumAddress, tEthereumAddress, tEthereumAddress,tEthereumAddress, string, string], + args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], verify?: boolean ) => { const instance = await withSaveAndVerify( @@ -578,20 +553,11 @@ args: [tEthereumAddress, tEthereumAddress, tEthereumAddress,tEthereumAddress, st [], verify ); - - await instance.initialize( - args[0], - args[2], - args[1], - args[3], - "18", - args[4], - args[5], - ); + + await instance.initialize(args[0], args[2], args[1], args[3], '18', args[4], args[5]); return instance; -} - +}; export const deploySelfdestructTransferMock = async (verify?: boolean) => withSaveAndVerify( diff --git a/helpers/types.ts b/helpers/types.ts index 00c7181b..d8e17fcf 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -287,12 +287,7 @@ export type iLpPoolAssets = Pick< export type iMaticPoolAssets = Pick< iAssetsWithoutUSD, - | 'DAI' - | 'USDC' - | 'USDT' - | 'WBTC' - | 'WETH' - | 'WMATIC' + 'DAI' | 'USDC' | 'USDT' | 'WBTC' | 'WETH' | 'WMATIC' >; export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; @@ -353,7 +348,7 @@ export interface IReserveParams extends IReserveBorrowParams, IReserveCollateral } export interface IInterestRateStrategyParams { - name: string, + name: string; optimalUtilizationRate: string; baseVariableBorrowRate: string; variableRateSlope1: string; @@ -474,6 +469,7 @@ export interface ICommonConfiguration { ReservesConfig: iMultiPoolsAssets; ATokenDomainSeparator: iParamsPerNetwork; WETH: iParamsPerNetwork; + WethGateway: iParamsPerNetwork; ReserveFactorTreasuryAddress: iParamsPerNetwork; } @@ -494,4 +490,3 @@ export interface ITokenAddress { } export type PoolConfiguration = ICommonConfiguration | IAaveConfiguration; - diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index efe71af3..ab233b09 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -165,6 +165,15 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.mumbai]: '', [eEthereumNetwork.matic]: '', }, + WethGateway: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, TokenDistributor: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.buidlerevm]: '', diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index 8f927258..1b7f403a 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -168,6 +168,15 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.mumbai]: '', [eEthereumNetwork.matic]: '', }, + WethGateway: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, TokenDistributor: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.buidlerevm]: '', diff --git a/package.json b/package.json index 3119ccb2..cd067de1 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ "test-permit": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-permit.spec.ts", "test-stable-and-atokens": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-transfer.spec.ts test-suites/test-aave/stable-token.spec.ts", "test-subgraph:scenarios": "hardhat --network hardhatevm_docker test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/subgraph-scenarios.spec.ts", - "test-weth": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/weth-gateway.spec.ts", + "test-weth:main": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/weth-gateway.spec.ts", + "test-weth:lp": "hardhat test test-suites/test-lp/__setup.spec.ts test-suites/test-lp/weth-gateway.spec.ts", "test-uniswap": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/uniswapAdapters*.spec.ts", "test:main:check-list": "MAINNET_FORK=true TS_NODE_TRANSPILE_ONLY=1 hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/mainnet/check-list.spec.ts", "dev:coverage": "buidler compile --force && buidler coverage --network coverage", diff --git a/tasks/deployments/deploy-wethGateWay.ts b/tasks/deployments/deploy-wethGateWay.ts new file mode 100644 index 00000000..83611efc --- /dev/null +++ b/tasks/deployments/deploy-wethGateWay.ts @@ -0,0 +1,21 @@ +import { task } from 'hardhat/config'; + +import { deployWETHGateway } from '../../helpers/contracts-deployments'; + +const CONTRACT_NAME = 'WETHGateway'; + +task(`deploy-${CONTRACT_NAME}`, `Deploys the ${CONTRACT_NAME} contract`) + .addParam('weth', 'Address of the weth token') + .addFlag('verify', `Verify ${CONTRACT_NAME} contract via Etherscan API.`) + .setAction(async ({ weth, verify }, localBRE) => { + await localBRE.run('set-DRE'); + + if (!localBRE.network.config.chainId) { + throw new Error('INVALID_CHAIN_ID'); + } + + const wethGateWay = await deployWETHGateway([weth], verify); + console.log(`${CONTRACT_NAME}.address`, wethGateWay.address); + + console.log(`\tFinished ${CONTRACT_NAME} deployment`); + }); diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index 983b7454..6c11ad6d 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -5,7 +5,10 @@ import { deployWalletBalancerProvider, deployAaveProtocolDataProvider, deployWETHGateway, + authorizeWETHGateway, } from '../../helpers/contracts-deployments'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { eEthereumNetwork } from '../../helpers/types'; import { ConfigNames, getReservesConfigByPool, @@ -30,12 +33,14 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ verify, pool }, localBRE) => { await localBRE.run('set-DRE'); + const network = localBRE.network.name; const poolConfig = loadPoolConfig(pool); const { ATokenNamePrefix, StableDebtTokenNamePrefix, VariableDebtTokenNamePrefix, SymbolPrefix, + WethGateway, } = poolConfig; const mockTokens = await getAllMockedTokens(); const allTokenAddresses = getAllTokenAddresses(mockTokens); @@ -87,6 +92,6 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') await insertContractAddressInDb(eContractid.AaveProtocolDataProvider, testHelpers.address); const lendingPoolAddress = await addressesProvider.getLendingPool(); - const wethAddress = await getWethAddress(poolConfig); - await deployWETHGateway([wethAddress, lendingPoolAddress]); + const gateWay = await getParamPerNetwork(WethGateway, network); + await authorizeWETHGateway(gateWay, lendingPoolAddress); }); diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 3c5bef85..28439d25 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -4,6 +4,7 @@ import { deployLendingPoolCollateralManager, deployWalletBalancerProvider, deployWETHGateway, + authorizeWETHGateway, } from '../../helpers/contracts-deployments'; import { loadPoolConfig, @@ -29,14 +30,15 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') await localBRE.run('set-DRE'); const network = localBRE.network.name; const poolConfig = loadPoolConfig(pool); - const { + const { ATokenNamePrefix, StableDebtTokenNamePrefix, VariableDebtTokenNamePrefix, SymbolPrefix, ReserveAssets, ReservesConfig, - LendingPoolCollateralManager + LendingPoolCollateralManager, + WethGateway, } = poolConfig as ICommonConfiguration; const reserveAssets = await getParamPerNetwork(ReserveAssets, network); @@ -66,9 +68,10 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') ); await configureReservesByHelper(ReservesConfig, reserveAssets, testHelpers, admin); - - - let collateralManagerAddress = await getParamPerNetwork(LendingPoolCollateralManager, network); + let collateralManagerAddress = await getParamPerNetwork( + LendingPoolCollateralManager, + network + ); if (!collateralManagerAddress) { const collateralManager = await deployLendingPoolCollateralManager(verify); collateralManagerAddress = collateralManager.address; @@ -81,11 +84,9 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') await deployWalletBalancerProvider(verify); - const wethAddress = await getWethAddress(poolConfig); const lendingPoolAddress = await addressesProvider.getLendingPool(); - - await deployWETHGateway([wethAddress, lendingPoolAddress]); - + const gateWay = await getParamPerNetwork(WethGateway, network); + await authorizeWETHGateway(gateWay, lendingPoolAddress); } catch (err) { console.error(err); exit(1); diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index a244e5c9..00935f53 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -26,7 +26,9 @@ import { deployUniswapLiquiditySwapAdapter, deployUniswapRepayAdapter, deployFlashLiquidationAdapter, + authorizeWETHGateway, } from '../../helpers/contracts-deployments'; +import { eEthereumNetwork } from '../../helpers/types'; import { Signer } from 'ethers'; import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types'; import { MintableERC20 } from '../../types/MintableERC20'; @@ -95,7 +97,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const aaveAdmin = await deployer.getAddress(); const mockTokens = await deployAllMockTokens(deployer); - console.log("Deployed mocks"); + console.log('Deployed mocks'); const addressesProvider = await deployLendingPoolAddressesProvider(AaveConfig.MarketId); await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin)); @@ -192,7 +194,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { ); const mockAggregators = await deployAllMockAggregators(MOCK_CHAINLINK_AGGREGATORS_PRICES); - console.log("Mock aggs deployed"); + console.log('Mock aggs deployed'); const allTokenAddresses = Object.entries(mockTokens).reduce( (accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, tokenContract]) => ({ ...accum, @@ -238,7 +240,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const config = loadPoolConfig(ConfigNames.Aave); - const { + const { ATokenNamePrefix, StableDebtTokenNamePrefix, VariableDebtTokenNamePrefix, @@ -281,7 +283,8 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { await deployWalletBalancerProvider(); - await deployWETHGateway([mockTokens.WETH.address, lendingPoolAddress]); + const gateWay = await deployWETHGateway([mockTokens.WETH.address]); + await authorizeWETHGateway(gateWay.address, lendingPoolAddress); console.timeEnd('setup'); }; diff --git a/test-suites/test-aave/weth-gateway.spec.ts b/test-suites/test-aave/weth-gateway.spec.ts index 22939f5c..b1980d68 100644 --- a/test-suites/test-aave/weth-gateway.spec.ts +++ b/test-suites/test-aave/weth-gateway.spec.ts @@ -14,7 +14,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => const depositSize = parseEther('5'); const daiSize = parseEther('10000'); it('Deposit WETH via WethGateway and DAI', async () => { - const { users, wethGateway, aWETH } = testEnv; + const { users, wethGateway, aWETH, pool } = testEnv; const user = users[1]; const depositor = users[0]; @@ -22,10 +22,12 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Deposit liquidity with native ETH await wethGateway .connect(depositor.signer) - .depositETH(depositor.address, '0', { value: depositSize }); + .depositETH(pool.address, depositor.address, '0', { value: depositSize }); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + await wethGateway + .connect(user.signer) + .depositETH(pool.address, user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -53,7 +55,9 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Partial Withdraw and send native Ether to user const { gasUsed: withdrawGas } = await waitForTx( - await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) + await wethGateway + .connect(user.signer) + .withdrawETH(pool.address, partialWithdraw, user.address) ); const afterPartialEtherBalance = await user.signer.getBalance(); @@ -87,7 +91,9 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Full withdraw const { gasUsed: withdrawGas } = await waitForTx( - await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) + await wethGateway + .connect(user.signer) + .withdrawETH(pool.address, MAX_UINT_AMOUNT, user.address) ); const afterFullEtherBalance = await user.signer.getBalance(); @@ -111,7 +117,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Deposit with native ETH await wethGateway .connect(depositor.signer) - .depositETH(depositor.address, '0', { value: depositSize }); + .depositETH(pool.address, depositor.address, '0', { value: depositSize }); const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address @@ -142,7 +148,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) + .repayETH(pool.address, MAX_UINT_AMOUNT, '1', user.address, { value: repaySize }) ); const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address); @@ -166,7 +172,9 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + await wethGateway + .connect(user.signer) + .depositETH(pool.address, user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -187,7 +195,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(partialPayment, '2', user.address, { value: partialPayment }) + .repayETH(pool.address, partialPayment, '2', user.address, { value: partialPayment }) ); const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); @@ -197,14 +205,14 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) + .repayETH(pool.address, MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); }); it('Borrow ETH via delegateApprove ETH and repays back', async () => { - const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; + const { users, wethGateway, aWETH, weth, helpersContract, pool } = testEnv; const borrowSize = parseEther('1'); const user = users[2]; const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( @@ -216,7 +224,9 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => expect(priorDebtBalance).to.be.eq(zero); // Deposit WETH with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + await wethGateway + .connect(user.signer) + .depositETH(pool.address, user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -229,7 +239,9 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => ); // Borrows ETH with WETH as collateral - await waitForTx(await wethGateway.connect(user.signer).borrowETH(borrowSize, '2', '0')); + await waitForTx( + await wethGateway.connect(user.signer).borrowETH(pool.address, borrowSize, '2', '0') + ); const debtBalance = await varDebtToken.balanceOf(user.address); @@ -239,7 +251,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) + .repayETH(pool.address, MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); @@ -297,18 +309,6 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => ).to.be.revertedWith('Fallback not allowed'); }); - it('Getters should retrieve correct state', async () => { - const { aWETH, weth, pool, wethGateway } = testEnv; - - const WETHAddress = await wethGateway.getWETHAddress(); - const aWETHAddress = await wethGateway.getAWETHAddress(); - const poolAddress = await wethGateway.getLendingPoolAddress(); - - expect(WETHAddress).to.be.equal(weth.address); - expect(aWETHAddress).to.be.equal(aWETH.address); - expect(poolAddress).to.be.equal(pool.address); - }); - it('Owner can do emergency token recovery', async () => { const { users, dai, wethGateway, deployer } = testEnv; const user = users[0]; diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-lp/__setup.spec.ts index 69d54269..e7515f25 100644 --- a/test-suites/test-lp/__setup.spec.ts +++ b/test-suites/test-lp/__setup.spec.ts @@ -26,6 +26,7 @@ import { deployUniswapLiquiditySwapAdapter, deployUniswapRepayAdapter, deployFlashLiquidationAdapter, + authorizeWETHGateway } from '../../helpers/contracts-deployments'; import { Signer } from 'ethers'; import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types'; @@ -280,7 +281,8 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { await deployWalletBalancerProvider(); - await deployWETHGateway([mockTokens.WETH.address, lendingPoolAddress]); + const gateWay = await deployWETHGateway([mockTokens.WETH.address]); + await authorizeWETHGateway(gateWay.address, lendingPoolAddress); console.timeEnd('setup'); }; diff --git a/test-suites/test-lp/weth-gateway.spec.ts b/test-suites/test-lp/weth-gateway.spec.ts index b8a0216a..80a3b169 100644 --- a/test-suites/test-lp/weth-gateway.spec.ts +++ b/test-suites/test-lp/weth-gateway.spec.ts @@ -15,7 +15,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => const depositSize = parseEther('5'); const daiSize = parseEther('10000'); it('Deposit WETH via WethGateway and DAI', async () => { - const { users, wethGateway, aWETH } = testEnv; + const { users, wethGateway, aWETH, pool } = testEnv; const user = users[1]; const depositor = users[0]; @@ -23,10 +23,10 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Deposit liquidity with native ETH await wethGateway .connect(depositor.signer) - .depositETH(depositor.address, '0', { value: depositSize }); + .depositETH(pool.address, depositor.address, '0', { value: depositSize }); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + await wethGateway.connect(user.signer).depositETH(pool.address, user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -54,7 +54,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Partial Withdraw and send native Ether to user const { gasUsed: withdrawGas } = await waitForTx( - await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address) + await wethGateway.connect(user.signer).withdrawETH(pool.address, partialWithdraw, user.address) ); const afterPartialEtherBalance = await user.signer.getBalance(); @@ -88,7 +88,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Full withdraw const { gasUsed: withdrawGas } = await waitForTx( - await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address) + await wethGateway.connect(user.signer).withdrawETH(pool.address, MAX_UINT_AMOUNT, user.address) ); const afterFullEtherBalance = await user.signer.getBalance(); @@ -112,7 +112,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => // Deposit with native ETH await wethGateway .connect(depositor.signer) - .depositETH(depositor.address, '0', { value: depositSize }); + .depositETH(pool.address, depositor.address, '0', { value: depositSize }); const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( weth.address @@ -168,7 +168,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress); // Deposit with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + await wethGateway.connect(user.signer).depositETH(pool.address, user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -189,7 +189,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(partialPayment, '2', user.address, { value: partialPayment }) + .repayETH(pool.address, partialPayment, '2', user.address, { value: partialPayment }) ); const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address); @@ -199,14 +199,14 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) + .repayETH(pool.address, MAX_UINT_AMOUNT, '2', user.address, { value: repaySize }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); }); it('Borrow ETH via delegateApprove ETH and repays back', async () => { - const { users, wethGateway, aWETH, weth, helpersContract } = testEnv; + const { users, wethGateway, aWETH, weth, helpersContract, pool } = testEnv; const borrowSize = parseEther('1'); const user = users[2]; const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( @@ -218,7 +218,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => expect(priorDebtBalance).to.be.eq(zero); // Deposit WETH with native ETH - await wethGateway.connect(user.signer).depositETH(user.address, '0', { value: depositSize }); + await wethGateway.connect(user.signer).depositETH(pool.address, user.address, '0', { value: depositSize }); const aTokensBalance = await aWETH.balanceOf(user.address); @@ -231,7 +231,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => ); // Borrows ETH with WETH as collateral - await waitForTx(await wethGateway.connect(user.signer).borrowETH(borrowSize, '2', '0')); + await waitForTx(await wethGateway.connect(user.signer).borrowETH(pool.address, borrowSize, '2', '0')); const debtBalance = await varDebtToken.balanceOf(user.address); @@ -241,7 +241,7 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => await waitForTx( await wethGateway .connect(user.signer) - .repayETH(MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) + .repayETH(pool.address, MAX_UINT_AMOUNT, '2', user.address, { value: borrowSize.mul(2) }) ); const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address); expect(debtBalanceAfterFullRepay).to.be.eq(zero); @@ -299,17 +299,6 @@ makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => ).to.be.revertedWith('Fallback not allowed'); }); - it('Getters should retrieve correct state', async () => { - const { aWETH, weth, pool, wethGateway } = testEnv; - - const WETHAddress = await wethGateway.getWETHAddress(); - const aWETHAddress = await wethGateway.getAWETHAddress(); - const poolAddress = await wethGateway.getLendingPoolAddress(); - - expect(WETHAddress).to.be.equal(weth.address); - expect(aWETHAddress).to.be.equal(aWETH.address); - expect(poolAddress).to.be.equal(pool.address); - }); it('Owner can do emergency token recovery', async () => { const { users, dai, wethGateway, deployer } = testEnv; From 18aac08061a68482caaf183851d0d63ed3052962 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 22 Feb 2021 14:58:16 +0100 Subject: [PATCH 138/219] Added full script and config for kovan --- markets/aave/commons.ts | 2 +- package-lock.json | 25493 +++++++++++++++- tasks/deployments/deploy-wethGateWay.ts | 21 - tasks/full/5-deploy-wethGateWay.ts | 32 + .../full/{5_initialize.ts => 6-initialize.ts} | 7 +- tasks/migrations/aave.mainnet.ts | 9 +- tasks/verifications/1_general.ts | 5 +- 7 files changed, 25414 insertions(+), 155 deletions(-) delete mode 100644 tasks/deployments/deploy-wethGateWay.ts create mode 100644 tasks/full/5-deploy-wethGateWay.ts rename tasks/full/{5_initialize.ts => 6-initialize.ts} (93%) diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index ab233b09..39be628b 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -169,7 +169,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.kovan]: '0xf99b8E67a0E044734B01EC4586D1c88C9a869718', [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '', [eEthereumNetwork.tenderlyMain]: '', diff --git a/package-lock.json b/package-lock.json index bbe177fa..129f12e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,25338 @@ { "name": "@aave/protocol-v2", "version": "1.0.1", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "@aave/protocol-v2", + "version": "1.0.1", + "license": "AGPLv3", + "dependencies": { + "tmp-promise": "^3.0.2" + }, + "devDependencies": { + "@nomiclabs/buidler": "^1.4.7", + "@nomiclabs/buidler-ethers": "2.0.0", + "@nomiclabs/buidler-etherscan": "^2.1.0", + "@nomiclabs/buidler-waffle": "2.0.0", + "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomiclabs/hardhat-waffle": "^2.0.0", + "@openzeppelin/contracts": "3.1.0", + "@tenderly/hardhat-tenderly": "^1.1.0-beta.3", + "@typechain/ethers-v4": "1.0.0", + "@typechain/ethers-v5": "^2.0.0", + "@typechain/truffle-v4": "2.0.2", + "@typechain/truffle-v5": "2.0.2", + "@typechain/web3-v1": "1.0.0", + "@types/chai": "4.2.11", + "@types/lowdb": "1.0.9", + "@types/mocha": "7.0.2", + "@types/node": "14.0.5", + "bignumber.js": "9.0.0", + "buidler-typechain": "0.1.1", + "chai": "4.2.0", + "chai-bignumber": "3.0.0", + "chai-bn": "^0.2.1", + "dotenv": "^8.2.0", + "eth-sig-util": "2.5.3", + "ethereum-waffle": "3.0.2", + "ethereumjs-util": "7.0.2", + "ethers": "^5.0.19", + "globby": "^11.0.1", + "hardhat": "^2.0.8", + "hardhat-gas-reporter": "^1.0.0", + "hardhat-typechain": "^0.3.3", + "husky": "^4.2.5", + "lowdb": "1.0.0", + "prettier": "^2.0.5", + "prettier-plugin-solidity": "^1.0.0-alpha.53", + "pretty-quick": "^2.0.1", + "solidity-coverage": "0.7.10", + "temp-hardhat-etherscan": "^2.0.2", + "ts-generator": "^0.1.1", + "ts-node": "^8.10.2", + "tslint": "^6.1.2", + "tslint-config-prettier": "^1.18.0", + "tslint-plugin-prettier": "^2.3.0", + "typechain": "^4.0.0", + "typescript": "^4.0.5" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "node_modules/@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@ensdomains/ens": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/@ensdomains/ens/-/ens-0.4.5.tgz", + "integrity": "sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.2", + "eth-ens-namehash": "^2.0.8", + "solc": "^0.4.20", + "testrpc": "0.0.1", + "web3-utils": "^1.0.0-beta.31" + } + }, + "node_modules/@ensdomains/ens/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/@ensdomains/ens/node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "node_modules/@ensdomains/ens/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@ensdomains/ens/node_modules/require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "node_modules/@ensdomains/ens/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/@ensdomains/ens/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@ensdomains/ens/node_modules/solc": { + "version": "0.4.26", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.26.tgz", + "integrity": "sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA==", + "dev": true, + "dependencies": { + "fs-extra": "^0.30.0", + "memorystream": "^0.3.1", + "require-from-string": "^1.1.0", + "semver": "^5.3.0", + "yargs": "^4.7.1" + }, + "bin": { + "solcjs": "solcjs" + } + }, + "node_modules/@ensdomains/ens/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "node_modules/@ensdomains/ens/node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "node_modules/@ensdomains/ens/node_modules/yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "dev": true, + "dependencies": { + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.0.3", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" + } + }, + "node_modules/@ensdomains/ens/node_modules/yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "dev": true, + "dependencies": { + "camelcase": "^3.0.0", + "lodash.assign": "^4.0.6" + } + }, + "node_modules/@ensdomains/resolver": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@ensdomains/resolver/-/resolver-0.2.4.tgz", + "integrity": "sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA==", + "dev": true + }, + "node_modules/@ethereum-waffle/chai": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/chai/-/chai-3.2.0.tgz", + "integrity": "sha512-3mvI7luX8FSAX2yjklSN8rw8F8RNaMzZDadDkS9JvmoM4khByGe3mDn8rVroneBAcFusXJfL6BEssGj5S4mD7Q==", + "dev": true, + "dependencies": { + "@ethereum-waffle/provider": "^3.2.0", + "ethers": "^5.0.0" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/@ethereum-waffle/compiler": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/compiler/-/compiler-3.2.0.tgz", + "integrity": "sha512-Tg8YjbcVKQkNwhbiBf9Z4kKPolPO0IB+iYwAdpXNwgyMOH74guIHhFGtKOCPoY4VXR75erGgeQIt2PzIn/szCA==", + "dev": true, + "dependencies": { + "@resolver-engine/imports": "^0.3.3", + "@resolver-engine/imports-fs": "^0.3.3", + "@types/mkdirp": "^0.5.2", + "@types/node-fetch": "^2.5.5", + "ethers": "^5.0.1", + "mkdirp": "^0.5.1", + "node-fetch": "^2.6.0", + "solc": "^0.6.3" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/@ethereum-waffle/ens": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/ens/-/ens-3.2.0.tgz", + "integrity": "sha512-n4EYJDLAwN2X+2EsZMasXRlz5gYp39Tmy18RU4f6ZdnTNuVNw1BNkCC9VzrQooHGvHLjKZFPvcl+FRfBO+Xcyw==", + "dev": true, + "dependencies": { + "@ensdomains/ens": "^0.4.4", + "@ensdomains/resolver": "^0.2.4", + "ethers": "^5.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/@ethereum-waffle/mock-contract": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/mock-contract/-/mock-contract-3.2.0.tgz", + "integrity": "sha512-TfBt9ka2DXVxxIBee3WB0gSLgWCo9ZegqcdXjCz0QGlu+dEhL8W3+aLDYQoyx3kwlecfNl8EQ1V7g7GH8wrlMg==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.0.1", + "ethers": "^5.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/@ethereum-waffle/provider": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/provider/-/provider-3.2.0.tgz", + "integrity": "sha512-U9KyjMKIZuK4gi2kzWIJkAXYjtg0aIlEQ0F4yKqHMRyqAiSM6M4VJgn6tHisxe3Ev9z/jSnutKT8dyAEwlIYdw==", + "dev": true, + "dependencies": { + "@ethereum-waffle/ens": "^3.2.0", + "ethers": "^5.0.1", + "ganache-core": "^2.10.2", + "patch-package": "^6.2.2", + "postinstall-postinstall": "^2.1.0" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/@ethersproject/abi": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz", + "integrity": "sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==", + "dev": true, + "dependencies": { + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/@ethersproject/abstract-provider": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.5.tgz", + "integrity": "sha512-i/CjElAkzV7vQBAeoz+IpjGfcFYEP9eD7j3fzZ0fzTq03DO7PPnR+xkEZ1IoDXGwDS+55aLM1xvLDwB/Lx6IOQ==", + "dev": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/networks": "^5.0.3", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/transactions": "^5.0.5", + "@ethersproject/web": "^5.0.6" + } + }, + "node_modules/@ethersproject/abstract-signer": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.7.tgz", + "integrity": "sha512-8W8gy/QutEL60EoMEpvxZ8MFAEWs/JvH5nmZ6xeLXoZvmBCasGmxqHdYjo2cxg0nevkPkq9SeenSsBBZSCx+SQ==", + "dev": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3" + } + }, + "node_modules/@ethersproject/address": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.5.tgz", + "integrity": "sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA==", + "dev": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/rlp": "^5.0.3", + "bn.js": "^4.4.0" + } + }, + "node_modules/@ethersproject/base64": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.4.tgz", + "integrity": "sha512-4KRykQ7BQMeOXfvio1YITwHjxwBzh92UoXIdzxDE1p53CK28bbHPdsPNYo0wl0El7lJAMpT2SOdL0hhbWRnyIA==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4" + } + }, + "node_modules/@ethersproject/basex": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.0.4.tgz", + "integrity": "sha512-ixIr/kKiAoSzOnSc777AGIOAhKai5Ivqr4HO/Gz+YG+xkfv6kqD6AW4ga9vM20Wwb0QBhh3LoRWTu4V1K+x9Ew==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/properties": "^5.0.3" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.8.tgz", + "integrity": "sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "bn.js": "^4.4.0" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.5.tgz", + "integrity": "sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ==", + "dev": true, + "dependencies": { + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.5.tgz", + "integrity": "sha512-foaQVmxp2+ik9FrLUCtVrLZCj4M3Ibgkqvh+Xw/vFRSerkjVSYePApaVE5essxhoSlF1U9oXfWY09QI2AXtgKA==", + "dev": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7" + } + }, + "node_modules/@ethersproject/contracts": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.0.5.tgz", + "integrity": "sha512-tFI255lFbmbqMkgnuyhDWHl3yWqttPlReplYuVvDCT/SuvBjLR4ad2uipBlh1fh5X1ipK9ettAoV4S0HKim4Kw==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.0.5", + "@ethersproject/abstract-provider": "^5.0.4", + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.6.tgz", + "integrity": "sha512-Gvh57v6BWhwnud6l7tMfQm32PRQ2DYx2WaAAQmAxAfYvmzUkpQCBstnGeNMXIL8/2wdkvcB2u+WZRWaZtsFuUQ==", + "dev": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.0.6", + "@ethersproject/address": "^5.0.5", + "@ethersproject/bignumber": "^5.0.8", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.4", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/@ethersproject/hdnode": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.0.5.tgz", + "integrity": "sha512-Ho4HZaK+KijE5adayvjAGusWMnT0mgwGa5hGMBofBOgX9nqiKf6Wxx68SXBGI1/L3rmKo6mlAjxUd8gefs0teQ==", + "dev": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/basex": "^5.0.3", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/pbkdf2": "^5.0.3", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/sha2": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4", + "@ethersproject/strings": "^5.0.4", + "@ethersproject/transactions": "^5.0.5", + "@ethersproject/wordlists": "^5.0.4" + } + }, + "node_modules/@ethersproject/json-wallets": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.0.7.tgz", + "integrity": "sha512-dgOn9JtGgjT28mDXs4LYY2rT4CzS6bG/rxoYuPq3TLHIf6nmvBcr33Fee6RrM/y8UAx4gyIkf6wb2cXsOctvQQ==", + "dev": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/address": "^5.0.4", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/hdnode": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/pbkdf2": "^5.0.3", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/random": "^5.0.3", + "@ethersproject/strings": "^5.0.4", + "@ethersproject/transactions": "^5.0.5", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.4.tgz", + "integrity": "sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "js-sha3": "0.5.7" + } + }, + "node_modules/@ethersproject/keccak256/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/@ethersproject/logger": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.6.tgz", + "integrity": "sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ==", + "dev": true + }, + "node_modules/@ethersproject/networks": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.4.tgz", + "integrity": "sha512-/wHDTRms5mpJ09BoDrbNdFWINzONe05wZRgohCXvEv39rrH/Gd/yAnct8wC0RsW3tmFOgjgQxuBvypIxuUynTw==", + "dev": true, + "dependencies": { + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/pbkdf2": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.0.4.tgz", + "integrity": "sha512-9jVBjHXQKfr9+3bkCg01a8Cd1H9e+7Kw3ZMIvAxD0lZtuzrXsJxm1hVwY9KA+PRUvgS/9tTP4viXQYwLAax7zg==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/sha2": "^5.0.3" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.4.tgz", + "integrity": "sha512-UdyX3GqBxFt15B0uSESdDNmhvEbK3ACdDXl2soshoPcneXuTswHDeA0LoPlnaZzhbgk4p6jqb4GMms5C26Qu6A==", + "dev": true, + "dependencies": { + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/providers": { + "version": "5.0.14", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.0.14.tgz", + "integrity": "sha512-K9QRRkkHWyprm3g4L8U9aPx5uyivznL4RYemkN2shCQumyGqFJ5SO+OtQrgebVm0JpGwFAUGugnhRUh49sjErw==", + "dev": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.0.4", + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/address": "^5.0.4", + "@ethersproject/basex": "^5.0.3", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/networks": "^5.0.3", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/random": "^5.0.3", + "@ethersproject/rlp": "^5.0.3", + "@ethersproject/sha2": "^5.0.3", + "@ethersproject/strings": "^5.0.4", + "@ethersproject/transactions": "^5.0.5", + "@ethersproject/web": "^5.0.6", + "bech32": "1.1.4", + "ws": "7.2.3" + } + }, + "node_modules/@ethersproject/providers/node_modules/ws": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", + "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==", + "dev": true, + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/@ethersproject/random": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.0.4.tgz", + "integrity": "sha512-AIZJhqs6Ba4/+U3lOjt3QZbP6b/kuuGLJUYFUonAgWmkTHwqsCwYnFvnHKQSUuHbXHvErp7WFXFlztx+yMn3kQ==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.4.tgz", + "integrity": "sha512-5qrrZad7VTjofxSsm7Zg/7Dr4ZOln4S2CqiDdOuTv6MBKnXj0CiBojXyuDy52M8O3wxH0CyE924hXWTDV1PQWQ==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/sha2": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.0.4.tgz", + "integrity": "sha512-0yFhf1mspxAfWdXXoPtK94adUeu1R7/FzAa+DfEiZTc76sz/vHXf0LSIazoR3znYKFny6haBxME+usbvvEcF3A==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "hash.js": "1.1.3" + } + }, + "node_modules/@ethersproject/sha2/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.5.tgz", + "integrity": "sha512-Z1wY7JC1HVO4CvQWY2TyTTuAr8xK3bJijZw1a9G92JEmKdv1j255R/0YLBBcFTl2J65LUjtXynNJ2GbArPGi5g==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "elliptic": "6.5.3" + } + }, + "node_modules/@ethersproject/solidity": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.0.5.tgz", + "integrity": "sha512-DMFQ0ouXmNVoKWbGEUFGi8Urli4SJip9jXafQyFHWPRr5oJUqDVkNfwcyC37k+mhBG93k7qrYXCH2xJnGEOxHg==", + "dev": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/sha2": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.5.tgz", + "integrity": "sha512-JED6WaIV00xM/gvj8vSnd+0VWtDYdidTmavFRCTQakqfz+4tDo6Jz5LHgG+dd45h7ah7ykCHW0C7ZXWEDROCXQ==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/transactions": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.6.tgz", + "integrity": "sha512-htsFhOD+NMBxx676A8ehSuwVV49iqpSB+CkjPZ02tpNew0K6p8g0CZ46Z1ZP946gIHAU80xQ0NACHYrjIUaCFA==", + "dev": true, + "dependencies": { + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/rlp": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4" + } + }, + "node_modules/@ethersproject/units": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.0.6.tgz", + "integrity": "sha512-tsJuy4mipppdmooukRfhXt8fGx9nxvfvG6Xdy0RDm7LzHsjghjwQ69m2bCpId6SDSR1Uq1cQ9irPiUBSyWolUA==", + "dev": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/@ethersproject/wallet": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.0.7.tgz", + "integrity": "sha512-n2GX1+2Tc0qV8dguUcLkjNugINKvZY7u/5fEsn0skW9rz5+jHTR5IKMV6jSfXA+WjQT8UCNMvkI3CNcdhaPbTQ==", + "dev": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.0.4", + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/hdnode": "^5.0.4", + "@ethersproject/json-wallets": "^5.0.6", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/random": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4", + "@ethersproject/transactions": "^5.0.5", + "@ethersproject/wordlists": "^5.0.4" + } + }, + "node_modules/@ethersproject/web": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.9.tgz", + "integrity": "sha512-//QNlv1MSkOII1hv3+HQwWoiVFS+BMVGI0KYeUww4cyrEktnx1QIez5bTSab9s9fWTFaWKNmQNBwMbxAqPuYDw==", + "dev": true, + "dependencies": { + "@ethersproject/base64": "^5.0.3", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/@ethersproject/wordlists": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.0.5.tgz", + "integrity": "sha512-XA3ycFltVrCTQt04w5nHu3Xq5Z6HjqWsXaAYQHFdqtugyUsIumaO9S5MOwFFuUYTNkZUoT3jCRa/OBS+K4tLfA==", + "dev": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nomiclabs/buidler": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@nomiclabs/buidler/-/buidler-1.4.8.tgz", + "integrity": "sha512-OUnNWx+WXOJzueJCfyuEXu3qNMq1j9eGDDpgflpRwjPeiQQnvVzfbwrPjs0PlxOC3Xtmaxabtgek5wGxS1C7Ew==", + "dev": true, + "dependencies": { + "@nomiclabs/ethereumjs-vm": "^4.1.1", + "@sentry/node": "^5.18.1", + "@solidity-parser/parser": "^0.5.2", + "@types/bn.js": "^4.11.5", + "@types/lru-cache": "^5.1.0", + "abort-controller": "^3.0.0", + "ansi-escapes": "^4.3.0", + "chalk": "^2.4.2", + "chokidar": "^3.4.0", + "ci-info": "^2.0.0", + "debug": "^4.1.1", + "deepmerge": "^2.1.0", + "download": "^7.1.0", + "enquirer": "^2.3.0", + "env-paths": "^2.2.0", + "eth-sig-util": "^2.5.2", + "ethereum-cryptography": "^0.1.2", + "ethereumjs-abi": "^0.6.8", + "ethereumjs-account": "^3.0.0", + "ethereumjs-block": "^2.2.0", + "ethereumjs-common": "^1.3.2", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^6.1.0", + "find-up": "^2.1.0", + "fp-ts": "1.19.3", + "fs-extra": "^7.0.1", + "glob": "^7.1.3", + "io-ts": "1.10.4", + "is-installed-globally": "^0.2.0", + "lodash": "^4.17.11", + "merkle-patricia-tree": "^3.0.0", + "mocha": "^7.1.2", + "node-fetch": "^2.6.0", + "qs": "^6.7.0", + "raw-body": "^2.4.1", + "semver": "^6.3.0", + "slash": "^3.0.0", + "solc": "0.6.8", + "source-map-support": "^0.5.13", + "ts-essentials": "^2.0.7", + "tsort": "0.0.1", + "uuid": "^3.3.2", + "ws": "^7.2.1" + }, + "bin": { + "buidler": "internal/cli/cli.js", + "builder": "internal/cli/cli-with-a-typo.js" + }, + "engines": { + "node": ">=8.2.0" + } + }, + "node_modules/@nomiclabs/buidler-ethers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/buidler-ethers/-/buidler-ethers-2.0.0.tgz", + "integrity": "sha512-Lf5XLClEeWYo6jVrGAqGBAcKTOP6IAChAR4qcDS36BkQnWakoRKcoSbwhr2YmTNTRAvgDWTmjQYbV17udJ+Alw==", + "dev": true + }, + "node_modules/@nomiclabs/buidler-etherscan": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/buidler-etherscan/-/buidler-etherscan-2.1.0.tgz", + "integrity": "sha512-Rh1PGCtIVNU9zDSnLn6WlJDMBM9LXzkwNnzRFnTrMdA+Aa9nMVX7qwbAXG9pyIIsuqNH6MRfk7CDvi8aMoojng==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.0.2", + "@ethersproject/address": "^5.0.2", + "cbor": "^5.0.2", + "ethereumjs-abi": "^0.6.8", + "node-fetch": "^2.6.0", + "semver": "^6.3.0" + } + }, + "node_modules/@nomiclabs/buidler-waffle": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/buidler-waffle/-/buidler-waffle-2.0.0.tgz", + "integrity": "sha512-slGUjMmooIFehk1EMz+gSD07x6RVhp9aEHCmjk5MDm9FuV0+1IhPrk0DDl9ZKYlb5dgTRSWOqzIOXLXhnjmt0A==", + "dev": true, + "dependencies": { + "@types/sinon-chai": "^3.2.3", + "@types/web3": "1.0.19" + } + }, + "node_modules/@nomiclabs/buidler/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz", + "integrity": "sha512-+XwqoO941bILTO4KDLIUJ37U42ySxw6it7jyoi0tKv0/VUcOrWKF1TCQWMv6dBDRlxpPQd273n9o5SVlYYLRWQ==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "async-eventemitter": "^0.2.2", + "core-js-pure": "^3.0.1", + "ethereumjs-account": "^3.0.0", + "ethereumjs-block": "^2.2.2", + "ethereumjs-blockchain": "^4.0.3", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.2", + "ethereumjs-util": "^6.2.0", + "fake-merkle-patricia-tree": "^1.0.1", + "functional-red-black-tree": "^1.0.1", + "merkle-patricia-tree": "^2.3.2", + "rustbn.js": "~0.2.0", + "safe-buffer": "^5.1.1", + "util.promisify": "^1.0.0" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/@nomiclabs/ethereumjs-vm/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/@nomiclabs/hardhat-ethers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.0.tgz", + "integrity": "sha512-fIi6XP9PgKqwSNVcLDr6S5hvGlc21PendaLD5eGdXEXc9aYQ0OJX8Mk3evs+p78x7W9n9U3ZcKtTiGc1+YScDw==", + "dev": true + }, + "node_modules/@nomiclabs/hardhat-waffle": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.0.tgz", + "integrity": "sha512-CnG9JC0rgqa68LTgyETxBUEWYAovvNGVs5abqaXjG80eF7iMLjDjM8IjOM87siAaxaxFCf6VBMJmtueqVq7jZw==", + "dev": true, + "dependencies": { + "@types/sinon-chai": "^3.2.3", + "@types/web3": "1.0.19" + } + }, + "node_modules/@openzeppelin/contracts": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-3.1.0.tgz", + "integrity": "sha512-dVXDnUKxrAKLzPdCRkz+N8qsVkK1XxJ6kk3zuI6zaQmcKxN7CkizoDP7lXxcs/Mi2I0mxceTRjJBqlzFffLJrQ==", + "dev": true + }, + "node_modules/@resolver-engine/core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz", + "integrity": "sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ==", + "dev": true, + "dependencies": { + "debug": "^3.1.0", + "is-url": "^1.2.4", + "request": "^2.85.0" + } + }, + "node_modules/@resolver-engine/core/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@resolver-engine/fs": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@resolver-engine/fs/-/fs-0.3.3.tgz", + "integrity": "sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ==", + "dev": true, + "dependencies": { + "@resolver-engine/core": "^0.3.3", + "debug": "^3.1.0" + } + }, + "node_modules/@resolver-engine/fs/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@resolver-engine/imports": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@resolver-engine/imports/-/imports-0.3.3.tgz", + "integrity": "sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q==", + "dev": true, + "dependencies": { + "@resolver-engine/core": "^0.3.3", + "debug": "^3.1.0", + "hosted-git-info": "^2.6.0", + "path-browserify": "^1.0.0", + "url": "^0.11.0" + } + }, + "node_modules/@resolver-engine/imports-fs": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz", + "integrity": "sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA==", + "dev": true, + "dependencies": { + "@resolver-engine/fs": "^0.3.3", + "@resolver-engine/imports": "^0.3.3", + "debug": "^3.1.0" + } + }, + "node_modules/@resolver-engine/imports-fs/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@resolver-engine/imports/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@sentry/core": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.27.4.tgz", + "integrity": "sha512-IbI37cIZU/qBQouuUXaLbGF/9xYFp5STqmj1Gv64l0IZe4JnEp06V3yD5GxQ/mJ78vSfOqfwLooVCUw9FA61sQ==", + "dev": true, + "dependencies": { + "@sentry/hub": "5.27.4", + "@sentry/minimal": "5.27.4", + "@sentry/types": "5.27.4", + "@sentry/utils": "5.27.4", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/hub": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.27.4.tgz", + "integrity": "sha512-Ba1AqcjvSd2S+fpdXtXCrVXdrzq9E2Etb2eHUOkEYwSsq7StMOw7E8YHDPAo+to8zUbpMPz/Z9XGhFkyAbImGQ==", + "dev": true, + "dependencies": { + "@sentry/types": "5.27.4", + "@sentry/utils": "5.27.4", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/minimal": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.27.4.tgz", + "integrity": "sha512-biw5YfIQwvDoaRhLarfeRQ6MJ9UJOoDTmu8Kgg18prJy4rtfDowNJP0OBs5XAsTk6SWAXiE3g7vqUJBXgs7BWA==", + "dev": true, + "dependencies": { + "@sentry/hub": "5.27.4", + "@sentry/types": "5.27.4", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/node": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.27.4.tgz", + "integrity": "sha512-fv3FfQ6FiNV56LKk6t48oNw8qgf7X5fEhqhvKAoU7w+BL9AhChzh9v7sWn9ppDtRFE45tFfsZh0J/8ox5jpnfQ==", + "dev": true, + "dependencies": { + "@sentry/core": "5.27.4", + "@sentry/hub": "5.27.4", + "@sentry/tracing": "5.27.4", + "@sentry/types": "5.27.4", + "@sentry/utils": "5.27.4", + "cookie": "^0.4.1", + "https-proxy-agent": "^5.0.0", + "lru_map": "^0.3.3", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/tracing": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.27.4.tgz", + "integrity": "sha512-f3nG8ozCdcbFOzsnBCZ8w+/WfoNiAd0Ctr643L0rsFbaSzPWxbPMe3LNVrWwFVo6mHacG3/2HYmJ3CYMiWyTKQ==", + "dev": true, + "dependencies": { + "@sentry/hub": "5.27.4", + "@sentry/minimal": "5.27.4", + "@sentry/types": "5.27.4", + "@sentry/utils": "5.27.4", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/types": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.27.4.tgz", + "integrity": "sha512-41h3c7tgtSS8UBmfvEckSr+7V7/IVOjt/EiydyOd6s0N18zSFfGY5HdA6g+eFtIJK3DhWkUHCHZNanD5IY5YCQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/utils": { + "version": "5.27.4", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.27.4.tgz", + "integrity": "sha512-shV1I/q+Tob3hUxRj11DfMhe9PNDiv85hUUoRloZGGwu275dMwpswb2uwgSmjc2Ao4pnMKVx8TL1hC3kGLVHTQ==", + "dev": true, + "dependencies": { + "@sentry/types": "5.27.4", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@solidity-parser/parser": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.5.2.tgz", + "integrity": "sha512-uRyvnvVYmgNmTBpWDbBsH/0kPESQhQpEc4KsvMRLVzFJ1o1s0uIv0Y6Y9IB5vI1Dwz2CbS4X/y4Wyw/75cTFnQ==", + "dev": true + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@tenderly/hardhat-tenderly": { + "version": "1.1.0-beta.3", + "resolved": "https://registry.npmjs.org/@tenderly/hardhat-tenderly/-/hardhat-tenderly-1.1.0-beta.3.tgz", + "integrity": "sha512-CCiS3bBCc4MhOTI5oHRAuVy/Xan6/8oNnjiwbsRvG1hdUis+EL/UVwn5yrUM1qXQTPz/La3TvRkfEa/pq1gimw==", + "dev": true, + "dependencies": { + "axios": "^0.20.0", + "fs-extra": "^9.0.1", + "js-yaml": "^3.14.0" + } + }, + "node_modules/@tenderly/hardhat-tenderly/node_modules/fs-extra": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", + "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tenderly/hardhat-tenderly/node_modules/js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@tenderly/hardhat-tenderly/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "node_modules/@tenderly/hardhat-tenderly/node_modules/jsonfile/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@tenderly/hardhat-tenderly/node_modules/universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@truffle/error": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@truffle/error/-/error-0.0.7.tgz", + "integrity": "sha512-UIfVKsXSXocKnn5+RNklUXNoGd/JVj7V8KmC48TQzmjU33HQI86PX0JDS7SpHMHasI3w9X//1q7Lu7nZtj3Zzg==", + "dev": true + }, + "node_modules/@truffle/interface-adapter": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.3.3.tgz", + "integrity": "sha512-l3I4WFTfnBSIfG96IOBRtAIE6AHDAxcOUJE7W5zh9hocQwzQlGWc2yEyyTcLa0656TTM8RxaZZ2S/KdHHMvCaw==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.8", + "ethers": "^4.0.32", + "lodash": "^4.17.13", + "web3": "1.2.2" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/@types/node": { + "version": "12.19.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", + "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/ethers": { + "version": "4.0.48", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.48.tgz", + "integrity": "sha512-sZD5K8H28dOrcidzx9f8KYh8083n5BexIO3+SbE4jK83L85FxtpXZBCQdXb8gkg+7sBqomcLhhkU7UHL+F7I2g==", + "dev": true, + "dependencies": { + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "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" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/scrypt-js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/web3": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.2.tgz", + "integrity": "sha512-/ChbmB6qZpfGx6eNpczt5YSUBHEA5V2+iUCbn85EVb3Zv6FVxrOo5Tv7Lw0gE2tW7EEjASbCyp3mZeiZaCCngg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@types/node": "^12.6.1", + "web3-bzz": "1.2.2", + "web3-core": "1.2.2", + "web3-eth": "1.2.2", + "web3-eth-personal": "1.2.2", + "web3-net": "1.2.2", + "web3-shh": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/web3-utils/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/@truffle/provider": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@truffle/provider/-/provider-0.1.19.tgz", + "integrity": "sha512-ke8iQmzW4Y99+8iff8xQcc+mCNU4AkwtaZ/iSpmVD8qpLytw8/DSNCm0RiEz9/+I93Q1zqI4Jnij/rXnkS2Njw==", + "dev": true, + "dependencies": { + "@truffle/error": "^0.0.7", + "@truffle/interface-adapter": "^0.3.0", + "web3": "1.2.1" + } + }, + "node_modules/@truffle/provider/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@truffle/provider/node_modules/@types/node": { + "version": "10.17.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", + "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@truffle/provider/node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@truffle/provider/node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@truffle/provider/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/@truffle/provider/node_modules/ethers": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", + "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", + "dev": true, + "dependencies": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.3", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/@truffle/provider/node_modules/ethers/node_modules/elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "dev": true, + "dependencies": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/@truffle/provider/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@truffle/provider/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@truffle/provider/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@truffle/provider/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@truffle/provider/node_modules/scrypt-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", + "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/semver": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz", + "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@truffle/provider/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", + "dev": true + }, + "node_modules/@truffle/provider/node_modules/web3": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.1.tgz", + "integrity": "sha512-nNMzeCK0agb5i/oTWNdQ1aGtwYfXzHottFP2Dz0oGIzavPMGSKyVlr8ibVb1yK5sJBjrWVnTdGaOC2zKDFuFRw==", + "dev": true, + "dependencies": { + "web3-bzz": "1.2.1", + "web3-core": "1.2.1", + "web3-eth": "1.2.1", + "web3-eth-personal": "1.2.1", + "web3-net": "1.2.1", + "web3-shh": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-bzz": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.1.tgz", + "integrity": "sha512-LdOO44TuYbGIPfL4ilkuS89GQovxUpmLz6C1UC7VYVVRILeZS740FVB3j9V4P4FHUk1RenaDfKhcntqgVCHtjw==", + "dev": true, + "dependencies": { + "got": "9.6.0", + "swarm-js": "0.1.39", + "underscore": "1.9.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.1.tgz", + "integrity": "sha512-5ODwIqgl8oIg/0+Ai4jsLxkKFWJYE0uLuE1yUKHNVCL4zL6n3rFjRMpKPokd6id6nJCNgeA64KdWQ4XfpnjdMg==", + "dev": true, + "dependencies": { + "web3-core-helpers": "1.2.1", + "web3-core-method": "1.2.1", + "web3-core-requestmanager": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-core-helpers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.1.tgz", + "integrity": "sha512-Gx3sTEajD5r96bJgfuW377PZVFmXIH4TdqDhgGwd2lZQCcMi+DA4TgxJNJGxn0R3aUVzyyE76j4LBrh412mXrw==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-eth-iban": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-core-method": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.1.tgz", + "integrity": "sha512-Ghg2WS23qi6Xj8Od3VCzaImLHseEA7/usvnOItluiIc5cKs00WYWsNy2YRStzU9a2+z8lwQywPYp0nTzR/QXdQ==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.1", + "web3-core-promievent": "1.2.1", + "web3-core-subscriptions": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-core-promievent": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.1.tgz", + "integrity": "sha512-IVUqgpIKoeOYblwpex4Hye6npM0aMR+kU49VP06secPeN0rHMyhGF0ZGveWBrGvf8WDPI7jhqPBFIC6Jf3Q3zw==", + "dev": true, + "dependencies": { + "any-promise": "1.3.0", + "eventemitter3": "3.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-core-requestmanager": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.1.tgz", + "integrity": "sha512-xfknTC69RfYmLKC+83Jz73IC3/sS2ZLhGtX33D4Q5nQ8yc39ElyAolxr9sJQS8kihOcM6u4J+8gyGMqsLcpIBg==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.1", + "web3-providers-http": "1.2.1", + "web3-providers-ipc": "1.2.1", + "web3-providers-ws": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-core-subscriptions": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.1.tgz", + "integrity": "sha512-nmOwe3NsB8V8UFsY1r+sW6KjdOS68h8nuh7NzlWxBQT/19QSUGiERRTaZXWu5BYvo1EoZRMxCKyCQpSSXLc08g==", + "dev": true, + "dependencies": { + "eventemitter3": "3.1.2", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.1.tgz", + "integrity": "sha512-/2xly4Yry5FW1i+uygPjhfvgUP/MS/Dk+PDqmzp5M88tS86A+j8BzKc23GrlA8sgGs0645cpZK/999LpEF5UdA==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core": "1.2.1", + "web3-core-helpers": "1.2.1", + "web3-core-method": "1.2.1", + "web3-core-subscriptions": "1.2.1", + "web3-eth-abi": "1.2.1", + "web3-eth-accounts": "1.2.1", + "web3-eth-contract": "1.2.1", + "web3-eth-ens": "1.2.1", + "web3-eth-iban": "1.2.1", + "web3-eth-personal": "1.2.1", + "web3-net": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-abi": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.1.tgz", + "integrity": "sha512-jI/KhU2a/DQPZXHjo2GW0myEljzfiKOn+h1qxK1+Y9OQfTcBMxrQJyH5AP89O6l6NZ1QvNdq99ThAxBFoy5L+g==", + "dev": true, + "dependencies": { + "ethers": "4.0.0-beta.3", + "underscore": "1.9.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-accounts": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.1.tgz", + "integrity": "sha512-26I4qq42STQ8IeKUyur3MdQ1NzrzCqPsmzqpux0j6X/XBD7EjZ+Cs0lhGNkSKH5dI3V8CJasnQ5T1mNKeWB7nQ==", + "dev": true, + "dependencies": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "scryptsy": "2.1.0", + "semver": "6.2.0", + "underscore": "1.9.1", + "uuid": "3.3.2", + "web3-core": "1.2.1", + "web3-core-helpers": "1.2.1", + "web3-core-method": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-accounts/node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-contract": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.1.tgz", + "integrity": "sha512-kYFESbQ3boC9bl2rYVghj7O8UKMiuKaiMkxvRH5cEDHil8V7MGEGZNH0slSdoyeftZVlaWSMqkRP/chfnKND0g==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core": "1.2.1", + "web3-core-helpers": "1.2.1", + "web3-core-method": "1.2.1", + "web3-core-promievent": "1.2.1", + "web3-core-subscriptions": "1.2.1", + "web3-eth-abi": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-ens": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.1.tgz", + "integrity": "sha512-lhP1kFhqZr2nnbu3CGIFFrAnNxk2veXpOXBY48Tub37RtobDyHijHgrj+xTh+mFiPokyrapVjpFsbGa+Xzye4Q==", + "dev": true, + "dependencies": { + "eth-ens-namehash": "2.0.8", + "underscore": "1.9.1", + "web3-core": "1.2.1", + "web3-core-helpers": "1.2.1", + "web3-core-promievent": "1.2.1", + "web3-eth-abi": "1.2.1", + "web3-eth-contract": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-iban": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.1.tgz", + "integrity": "sha512-9gkr4QPl1jCU+wkgmZ8EwODVO3ovVj6d6JKMos52ggdT2YCmlfvFVF6wlGLwi0VvNa/p+0BjJzaqxnnG/JewjQ==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-eth-personal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.1.tgz", + "integrity": "sha512-RNDVSiaSoY4aIp8+Hc7z+X72H7lMb3fmAChuSBADoEc7DsJrY/d0R5qQDK9g9t2BO8oxgLrLNyBP/9ub2Hc6Bg==", + "dev": true, + "dependencies": { + "web3-core": "1.2.1", + "web3-core-helpers": "1.2.1", + "web3-core-method": "1.2.1", + "web3-net": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-net": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.1.tgz", + "integrity": "sha512-Yt1Bs7WgnLESPe0rri/ZoPWzSy55ovioaP35w1KZydrNtQ5Yq4WcrAdhBzcOW7vAkIwrsLQsvA+hrOCy7mNauw==", + "dev": true, + "dependencies": { + "web3-core": "1.2.1", + "web3-core-method": "1.2.1", + "web3-utils": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-providers-http": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.1.tgz", + "integrity": "sha512-BDtVUVolT9b3CAzeGVA/np1hhn7RPUZ6YYGB/sYky+GjeO311Yoq8SRDUSezU92x8yImSC2B+SMReGhd1zL+bQ==", + "dev": true, + "dependencies": { + "web3-core-helpers": "1.2.1", + "xhr2-cookies": "1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-providers-ipc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.1.tgz", + "integrity": "sha512-oPEuOCwxVx8L4CPD0TUdnlOUZwGBSRKScCz/Ws2YHdr9Ium+whm+0NLmOZjkjQp5wovQbyBzNa6zJz1noFRvFA==", + "dev": true, + "dependencies": { + "oboe": "2.1.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-providers-ws": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.1.tgz", + "integrity": "sha512-oqsQXzu+ejJACVHy864WwIyw+oB21nw/pI65/sD95Zi98+/HQzFfNcIFneF1NC4bVF3VNX4YHTNq2I2o97LAiA==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.1", + "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-shh": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.1.tgz", + "integrity": "sha512-/3Cl04nza5kuFn25bV3FJWa0s3Vafr5BlT933h26xovQ6HIIz61LmvNQlvX1AhFL+SNJOTcQmK1SM59vcyC8bA==", + "dev": true, + "dependencies": { + "web3-core": "1.2.1", + "web3-core-method": "1.2.1", + "web3-core-subscriptions": "1.2.1", + "web3-net": "1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@truffle/provider/node_modules/web3-utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.1.tgz", + "integrity": "sha512-Mrcn3l58L+yCKz3zBryM6JZpNruWuT0OCbag8w+reeNROSGVlXzUQkU+gtAwc9JCZ7tKUyg67+2YUGqUjVcyBA==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typechain/ethers-v4": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v4/-/ethers-v4-1.0.0.tgz", + "integrity": "sha512-tN9XV0ezbLaEuK6jC5gW6AiH4ihq9lMl1ifJr700oBjknKKNDO6jUSzUE56gJzhW/fuyGsb4zsCHwf3JCkBd9w==", + "dev": true + }, + "node_modules/@typechain/ethers-v5": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz", + "integrity": "sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw==", + "dev": true, + "dependencies": { + "ethers": "^5.0.2" + } + }, + "node_modules/@typechain/truffle-v4": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@typechain/truffle-v4/-/truffle-v4-2.0.2.tgz", + "integrity": "sha512-YoJAzgQZeark7lwInLnJ3u14JO980W5mVzFUkZny40+/WSPlox5Sa5IWLkULrgwkEWoiLA2sTpJ2tE7nCtSC2Q==", + "dev": true + }, + "node_modules/@typechain/truffle-v5": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@typechain/truffle-v5/-/truffle-v5-2.0.2.tgz", + "integrity": "sha512-g4N2kfol1S3g/QUkmpzukCGZiKWUdXsSms1be/+W4+R0DPMz1Q/76tY+C6bD7G/KeLhkiDKcnZFmNVNcAgjIfQ==", + "dev": true + }, + "node_modules/@typechain/web3-v1": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@typechain/web3-v1/-/web3-v1-1.0.0.tgz", + "integrity": "sha512-MM8PmsblePaxy5BCYEuPtR4ajigPf504VRQzZgFYqs6KuFnJxbOjF8jNYT12P6UvUX7us75Wc78QdbvOHbb4hA==", + "dev": true + }, + "node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/chai": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.11.tgz", + "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", + "dev": true + }, + "node_modules/@types/concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-OU2+C7X+5Gs42JZzXoto7yOQ0A0=", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/form-data": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", + "integrity": "sha1-yayFsqX9GENbjIXZ7LUObWyJP/g=", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.14.165", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.165.tgz", + "integrity": "sha512-tjSSOTHhI5mCHTy/OOXYIhi2Wt1qcbHmuXD1Ha7q70CgI/I71afO4XtLb/cVexki1oVYchpul/TOuu3Arcdxrg==", + "dev": true + }, + "node_modules/@types/lowdb": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/lowdb/-/lowdb-1.0.9.tgz", + "integrity": "sha512-LBRG5EPXFOJDoJc9jACstMhtMP+u+UkPYllBeGQXXKiaHc+uzJs9+/Aynb/5KkX33DtrIiKyzNVTPQc/4RcD6A==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lru-cache": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.0.tgz", + "integrity": "sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "node_modules/@types/mkdirp": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz", + "integrity": "sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/mocha": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", + "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "14.0.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.5.tgz", + "integrity": "sha512-90hiq6/VqtQgX8Sp0EzeIsv3r+ellbGj4URKj5j30tLlZvRUpnAe9YbYnjl3pJM93GyXU0tghHhvXHq+5rnCKA==", + "dev": true + }, + "node_modules/@types/node-fetch": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", + "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/pbkdf2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", + "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/prettier": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.5.tgz", + "integrity": "sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ==", + "dev": true + }, + "node_modules/@types/qs": { + "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 + }, + "node_modules/@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/secp256k1": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", + "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/sinon": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.8.tgz", + "integrity": "sha512-IVnI820FZFMGI+u1R+2VdRaD/82YIQTdqLYC9DLPszZuynAJDtCvCtCs3bmyL66s7FqRM3+LPX7DhHnVTaagDw==", + "dev": true, + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinon-chai": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.5.tgz", + "integrity": "sha512-bKQqIpew7mmIGNRlxW6Zli/QVyc3zikpGzCa797B/tRnD9OtHvZ/ts8sYXV+Ilj9u3QRaUEM8xrjgd1gwm1BpQ==", + "dev": true, + "dependencies": { + "@types/chai": "*", + "@types/sinon": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", + "integrity": "sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==", + "dev": true + }, + "node_modules/@types/underscore": { + "version": "1.10.24", + "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.10.24.tgz", + "integrity": "sha512-T3NQD8hXNW2sRsSbLNjF/aBo18MyJlbw0lSpQHB/eZZtScPdexN4HSa8cByYwTw9Wy7KuOFr81mlDQcQQaZ79w==", + "dev": true + }, + "node_modules/@types/web3": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/@types/web3/-/web3-1.0.19.tgz", + "integrity": "sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A==", + "dev": true, + "dependencies": { + "@types/bn.js": "*", + "@types/underscore": "*" + } + }, + "node_modules/@web3-js/scrypt-shim": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz", + "integrity": "sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "scryptsy": "^2.1.0", + "semver": "^6.3.0" + } + }, + "node_modules/@web3-js/websocket": { + "version": "1.0.30", + "resolved": "https://registry.npmjs.org/@web3-js/websocket/-/websocket-1.0.30.tgz", + "integrity": "sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "nan": "^2.14.0", + "typedarray-to-buffer": "^3.1.5", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@web3-js/websocket/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@web3-js/websocket/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/abstract-leveldown/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/address": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", + "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", + "dev": true, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true, + "engines": { + "node": ">=0.3.0" + } + }, + "node_modules/aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=", + "dev": true + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "dependencies": { + "type-fest": "^0.11.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/antlr4": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.8.0.tgz", + "integrity": "sha512-en/MxQ4OkPgGJQ3wD/muzj1uDnFSzdFIhc2+c6bHZokWkuBb6RRvFjpWhPxWLbgQvaEzldJZ0GSQpfSAaE3hqg==", + "dev": true + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/archive-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", + "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", + "dev": true, + "dependencies": { + "file-type": "^4.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/archive-type/node_modules/file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/async-eventemitter": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", + "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", + "dev": true, + "dependencies": { + "async": "^2.4.0" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "dev": true + }, + "node_modules/axios": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz", + "integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.10.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base-x": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", + "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "dev": true + }, + "node_modules/bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dev": true, + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/bl/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/bl/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/bl/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/blakejs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", + "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/body-parser/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-rsa/node_modules/bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "dev": true, + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/buffer-to-arraybuffer": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", + "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=", + "dev": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "node_modules/buidler-typechain": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buidler-typechain/-/buidler-typechain-0.1.1.tgz", + "integrity": "sha512-UXS6m0MUzomDWFfd6Jivbz/wmNZo4dpW/Qa6Lq89qhS/qms/j1haJqlMxsDu+tCi8i/JH/IZtFkiEmEQ1PgmhA==", + "dev": true + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "dev": true, + "dependencies": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", + "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.0" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "node_modules/caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "dev": true, + "dependencies": { + "get-proxy": "^2.0.0", + "isurl": "^1.0.0-alpha5", + "tunnel-agent": "^0.6.0", + "url-to-options": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cbor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-5.1.0.tgz", + "integrity": "sha512-qzEc7kUShdMbWTaUH7X+aHW8owvBU3FS0dfYR1lGYpoZr0mGJhhojLlZJH653x/DfeMZ56h315FRNBUIG1R7qg==", + "dev": true, + "dependencies": { + "bignumber.js": "^9.0.0", + "nofilter": "^1.0.4" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai-bignumber": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chai-bignumber/-/chai-bignumber-3.0.0.tgz", + "integrity": "sha512-SubOtaSI2AILWTWe2j0c6i2yFT/f9J6UBjeVGDuwDiPLkF/U5+/eTWUE3sbCZ1KgcPF6UJsDVYbIxaYA097MQA==", + "dev": true + }, + "node_modules/chai-bn": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/chai-bn/-/chai-bn-0.2.1.tgz", + "integrity": "sha512-01jt2gSXAw7UYFPT5K8d7HYjdXj2vyeIuE+0T/34FWzlNcVbs1JkPxRu7rYMfQnJhrHT8Nr6qjSf5ZwwLU2EYg==", + "dev": true + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/checkpoint-store": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz", + "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", + "dev": true, + "dependencies": { + "functional-red-black-tree": "^1.0.1" + } + }, + "node_modules/chokidar": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.1.2" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", + "dev": true, + "dependencies": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "dev": true + }, + "node_modules/command-line-args": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-4.0.7.tgz", + "integrity": "sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "find-replace": "^1.0.3", + "typical": "^2.6.1" + }, + "bin": { + "command-line-args": "bin/cli.js" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "node_modules/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "dev": true + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/core-js-pure": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.7.0.tgz", + "integrity": "sha512-EZD2ckZysv8MMt4J6HSvS9K2GdtlZtdBncKAmF9lr2n0c9dJUaUN88PSTjvgwCgQPWKTkERXITgS6JJRAnljtg==", + "dev": true, + "hasInstallScript": true + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/parse-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cosmiconfig/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/cross-spawn/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/death": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", + "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=", + "dev": true + }, + "node_modules/debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "dev": true, + "dependencies": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "dev": true, + "dependencies": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tar/node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "dev": true, + "dependencies": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2/node_modules/file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "dev": true, + "dependencies": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-targz/node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "dev": true, + "dependencies": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip/node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-unzip/node_modules/get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "dev": true, + "dependencies": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-unzip/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "node_modules/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "node_modules/deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.6.0" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-properties/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "node_modules/detect-port": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", + "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", + "dev": true, + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-to-object": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-to-object/-/dir-to-object-2.0.0.tgz", + "integrity": "sha512-sXs0JKIhymON7T1UZuO2Ud6VTNAx/VTBXIl4+3mjb2RgfOpt+hectX0x04YqPOPdkeOAKoJuKqwqnXXURNPNEA==", + "dev": true + }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", + "dev": true + }, + "node_modules/dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/download": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", + "integrity": "sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==", + "dev": true, + "dependencies": { + "archive-type": "^4.0.0", + "caw": "^2.0.1", + "content-disposition": "^0.5.2", + "decompress": "^4.2.0", + "ext-name": "^5.0.0", + "file-type": "^8.1.0", + "filenamify": "^2.0.0", + "get-stream": "^3.0.0", + "got": "^8.3.1", + "make-dir": "^1.2.0", + "p-event": "^2.1.0", + "pify": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "node_modules/elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding-down": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", + "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", + "dev": true, + "dependencies": { + "abstract-leveldown": "^5.0.0", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0", + "xtend": "^4.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/encoding-down/node_modules/abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/encoding-down/node_modules/level-codec": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", + "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", + "dev": true, + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/encoding-down/node_modules/level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/encoding-down/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/env-paths": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", + "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-abstract/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "dependencies": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "dependencies": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=0.12.0" + }, + "optionalDependencies": { + "source-map": "~0.2.0" + } + }, + "node_modules/escodegen/node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.7.0.tgz", + "integrity": "sha512-CStQYJgALoQBw3FsBzH0VOVDRnJ/ZimUlpLm226U8qgqYJfPOY/CPK6wyRInMxh73HSKg5wyRwdS4BVYYHwokA==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.1", + "jest-docblock": "^21.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima-extract-comments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz", + "integrity": "sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eth-ens-namehash": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", + "integrity": "sha1-IprEbsqG1S4MmR58sq74P/D2i88=", + "dev": true, + "dependencies": { + "idna-uts46-hx": "^2.3.1", + "js-sha3": "^0.5.7" + } + }, + "node_modules/eth-ens-namehash/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/eth-gas-reporter": { + "version": "0.2.19", + "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.19.tgz", + "integrity": "sha512-yQmbAa6O9/Yl/syNml2A0R+ZLQnJ9m9jogFXHzjMWVBMUVnAcEskOVyxaMYddkclZdYIMxE99tQy830C2jLsAQ==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.0.0-beta.146", + "@solidity-parser/parser": "^0.8.0", + "cli-table3": "^0.5.0", + "colors": "^1.1.2", + "ethereumjs-util": "6.2.0", + "ethers": "^4.0.40", + "fs-readdir-recursive": "^1.1.0", + "lodash": "^4.17.14", + "markdown-table": "^1.1.3", + "mocha": "^7.1.1", + "req-cwd": "^2.0.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.5", + "sha1": "^1.1.1", + "sync-request": "^6.0.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/@solidity-parser/parser": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.8.2.tgz", + "integrity": "sha512-8LySx3qrNXPgB5JiULfG10O3V7QTxI/TLzSw5hFQhXWSkVxZBAv4rZQ0sYgLEbc8g3L2lmnujj1hKul38Eu5NQ==", + "dev": true + }, + "node_modules/eth-gas-reporter/node_modules/ethereumjs-util": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz", + "integrity": "sha512-vb0XN9J2QGdZGIEKG2vXM+kUdEivUfU6Wmi5y0cg+LRhDYKnXIZ/Lz7XjFbHRR9VIKq2lVGLzGBkA++y2nOdOQ==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^2.0.0", + "rlp": "^2.2.3", + "secp256k1": "^3.0.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/ethers": { + "version": "4.0.48", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.48.tgz", + "integrity": "sha512-sZD5K8H28dOrcidzx9f8KYh8083n5BexIO3+SbE4jK83L85FxtpXZBCQdXb8gkg+7sBqomcLhhkU7UHL+F7I2g==", + "dev": true, + "dependencies": { + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "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" + } + }, + "node_modules/eth-gas-reporter/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/eth-gas-reporter/node_modules/keccak": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", + "integrity": "sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "inherits": "^2.0.4", + "nan": "^2.14.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=5.12.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/scrypt-js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", + "dev": true + }, + "node_modules/eth-gas-reporter/node_modules/secp256k1": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz", + "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "bip66": "^1.1.5", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "drbg.js": "^1.0.1", + "elliptic": "^6.5.2", + "nan": "^2.14.0", + "safe-buffer": "^5.1.2" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", + "dev": true + }, + "node_modules/eth-gas-reporter/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", + "dev": true + }, + "node_modules/eth-lib": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/eth-sig-util": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.5.3.tgz", + "integrity": "sha512-KpXbCKmmBUNUTGh9MRKmNkIPietfhzBqqYqysDavLseIiMUGl95k6UcPEkALAZlj41e9E6yioYXc1PC333RKqw==", + "dev": true, + "dependencies": { + "buffer": "^5.2.1", + "elliptic": "^6.4.0", + "ethereumjs-abi": "0.6.5", + "ethereumjs-util": "^5.1.1", + "tweetnacl": "^1.0.0", + "tweetnacl-util": "^0.15.0" + } + }, + "node_modules/eth-sig-util/node_modules/ethereumjs-abi": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz", + "integrity": "sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=", + "dev": true, + "dependencies": { + "bn.js": "^4.10.0", + "ethereumjs-util": "^4.3.0" + } + }, + "node_modules/eth-sig-util/node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz", + "integrity": "sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w==", + "dev": true, + "dependencies": { + "bn.js": "^4.8.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.0.0" + } + }, + "node_modules/eth-sig-util/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ethashjs": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ethashjs/-/ethashjs-0.0.8.tgz", + "integrity": "sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "buffer-xor": "^2.0.1", + "ethereumjs-util": "^7.0.2", + "miller-rabin": "^4.0.0" + } + }, + "node_modules/ethashjs/node_modules/buffer-xor": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", + "integrity": "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ethereum-bloom-filters": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.7.tgz", + "integrity": "sha512-cDcJJSJ9GMAcURiAWO3DxIEhTL/uWqlQnvgKpuYQzYPrt/izuGU+1ntQmHt0IRq6ADoSYHFnB+aCEFIldjhkMQ==", + "dev": true, + "dependencies": { + "js-sha3": "^0.8.0" + } + }, + "node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/ethereum-waffle": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/ethereum-waffle/-/ethereum-waffle-3.0.2.tgz", + "integrity": "sha512-VJQTL9oBbHIQRxQFuh1NBXoFXSlTIY6DrkPpO7CvevXRI9ixxq01nSc6hPYUIVy7s+U03sp4ply497O6mD3gsQ==", + "dev": true, + "dependencies": { + "@ethereum-waffle/chai": "^3.0.2", + "@ethereum-waffle/compiler": "^3.0.2", + "@ethereum-waffle/mock-contract": "^3.0.2", + "@ethereum-waffle/provider": "^3.0.2", + "ethers": "^5.0.1" + }, + "bin": { + "waffle": "bin/waffle" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/ethereumjs-abi": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", + "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ethereumjs-account": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz", + "integrity": "sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA==", + "dev": true, + "dependencies": { + "ethereumjs-util": "^6.0.0", + "rlp": "^2.2.1", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ethereumjs-account/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ethereumjs-block": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", + "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ethereumjs-block/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ethereumjs-block/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/ethereumjs-block/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ethereumjs-block/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/ethereumjs-block/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/ethereumjs-block/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ethereumjs-block/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/ethereumjs-block/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ethereumjs-blockchain": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz", + "integrity": "sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ==", + "dev": true, + "dependencies": { + "async": "^2.6.1", + "ethashjs": "~0.0.7", + "ethereumjs-block": "~2.2.2", + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.1.0", + "flow-stoplight": "^1.0.0", + "level-mem": "^3.0.1", + "lru-cache": "^5.1.1", + "rlp": "^2.2.2", + "semaphore": "^1.1.0" + } + }, + "node_modules/ethereumjs-blockchain/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ethereumjs-common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz", + "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==", + "dev": true + }, + "node_modules/ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "dev": true, + "dependencies": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ethereumjs-tx/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ethereumjs-util": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.2.tgz", + "integrity": "sha512-ATAP02eJLpAlWGfiKQddNrRfZpwXiTFhRN2EM/yLXMCdBW/xjKYblNKcx8GLzzrjXg0ymotck+lam1nuV90arQ==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^3.0.0", + "rlp": "^2.2.4", + "secp256k1": "^4.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ethereumjs-util/node_modules/bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "node_modules/ethers": { + "version": "5.0.19", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.0.19.tgz", + "integrity": "sha512-0AZnUgZh98q888WAd1oI3aLeI+iyDtrupjANVtPPS7O63lVopkR/No8A1NqSkgl/rU+b2iuu2mUZor6GD4RG2w==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "5.0.7", + "@ethersproject/abstract-provider": "5.0.5", + "@ethersproject/abstract-signer": "5.0.7", + "@ethersproject/address": "5.0.5", + "@ethersproject/base64": "5.0.4", + "@ethersproject/basex": "5.0.4", + "@ethersproject/bignumber": "5.0.8", + "@ethersproject/bytes": "5.0.5", + "@ethersproject/constants": "5.0.5", + "@ethersproject/contracts": "5.0.5", + "@ethersproject/hash": "5.0.6", + "@ethersproject/hdnode": "5.0.5", + "@ethersproject/json-wallets": "5.0.7", + "@ethersproject/keccak256": "5.0.4", + "@ethersproject/logger": "5.0.6", + "@ethersproject/networks": "5.0.4", + "@ethersproject/pbkdf2": "5.0.4", + "@ethersproject/properties": "5.0.4", + "@ethersproject/providers": "5.0.14", + "@ethersproject/random": "5.0.4", + "@ethersproject/rlp": "5.0.4", + "@ethersproject/sha2": "5.0.4", + "@ethersproject/signing-key": "5.0.5", + "@ethersproject/solidity": "5.0.5", + "@ethersproject/strings": "5.0.5", + "@ethersproject/transactions": "5.0.6", + "@ethersproject/units": "5.0.6", + "@ethersproject/wallet": "5.0.7", + "@ethersproject/web": "5.0.9", + "@ethersproject/wordlists": "5.0.5" + } + }, + "node_modules/ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", + "dev": true, + "dependencies": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ethjs-unit/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true + }, + "node_modules/ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dev": true, + "dependencies": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "dev": true + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/execa": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz", + "integrity": "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^3.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": "^8.12.0 || >=9.7.0" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/express/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "dependencies": { + "type": "^2.0.0" + } + }, + "node_modules/ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "dev": true, + "dependencies": { + "mime-db": "^1.28.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "dev": true, + "dependencies": { + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extract-comments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/extract-comments/-/extract-comments-1.1.0.tgz", + "integrity": "sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q==", + "dev": true, + "dependencies": { + "esprima-extract-comments": "^1.1.0", + "parse-code-context": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fake-merkle-patricia-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz", + "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", + "dev": true, + "dependencies": { + "checkpoint-store": "^1.1.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fast-glob/node_modules/micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/fastq": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz", + "integrity": "sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-type": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", + "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", + "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", + "dev": true, + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/find-replace": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-1.0.3.tgz", + "integrity": "sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A=", + "dev": true, + "dependencies": { + "array-back": "^1.0.4", + "test-value": "^2.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-replace/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/find-versions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", + "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "dev": true, + "dependencies": { + "semver-regex": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-yarn-workspace-root": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz", + "integrity": "sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==", + "dev": true, + "dependencies": { + "fs-extra": "^4.0.3", + "micromatch": "^3.1.4" + } + }, + "node_modules/find-yarn-workspace-root/node_modules/fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "dev": true, + "dependencies": { + "is-buffer": "~2.0.3" + }, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flow-stoplight": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz", + "integrity": "sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s=", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fp-ts": { + "version": "1.19.3", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", + "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", + "dev": true + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/from2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/from2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/from2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/from2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/ganache-cli": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.9.0.tgz", + "integrity": "sha512-ZdL6kPrApXF/O+f6uU431OJcwxMk69H3KPDSHHrMP82ZvZRNpDHbR+rVv7XX/YUeoQ5q6nZ2AFiGiFAVn9pfzA==", + "dev": true, + "dependencies": { + "ethereumjs-util": "6.1.0", + "source-map-support": "0.5.12", + "yargs": "13.2.4" + }, + "bin": { + "ganache-cli": "cli.js" + } + }, + "node_modules/ganache-cli/node_modules/ansi-regex": { + "version": "4.1.0", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/ansi-styles": { + "version": "3.2.1", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/bindings": { + "version": "1.5.0", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/ganache-cli/node_modules/bip66": { + "version": "1.1.5", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ganache-cli/node_modules/bn.js": { + "version": "4.11.8", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/brorand": { + "version": "1.1.0", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/browserify-aes": { + "version": "1.2.0", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ganache-cli/node_modules/buffer-from": { + "version": "1.1.1", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/buffer-xor": { + "version": "1.0.3", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/camelcase": { + "version": "5.3.1", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/cipher-base": { + "version": "1.0.4", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ganache-cli/node_modules/cliui": { + "version": "5.0.0", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/ganache-cli/node_modules/color-convert": { + "version": "1.9.3", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ganache-cli/node_modules/color-name": { + "version": "1.1.3", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/create-hash": { + "version": "1.2.0", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/ganache-cli/node_modules/create-hmac": { + "version": "1.1.7", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/ganache-cli/node_modules/cross-spawn": { + "version": "6.0.5", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/ganache-cli/node_modules/decamelize": { + "version": "1.2.0", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/drbg.js": { + "version": "1.0.1", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/ganache-cli/node_modules/elliptic": { + "version": "6.5.0", + "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/ganache-cli/node_modules/emoji-regex": { + "version": "7.0.3", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/end-of-stream": { + "version": "1.4.1", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/ganache-cli/node_modules/ethereumjs-util": { + "version": "6.1.0", + "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + }, + "node_modules/ganache-cli/node_modules/ethjs-util": { + "version": "0.1.6", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dev": true, + "dependencies": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-cli/node_modules/evp_bytestokey": { + "version": "1.0.3", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-cli/node_modules/execa": { + "version": "1.0.0", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/file-uri-to-path": { + "version": "1.0.0", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/find-up": { + "version": "3.0.0", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/get-caller-file": { + "version": "2.0.5", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/ganache-cli/node_modules/get-stream": { + "version": "4.1.0", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/hash-base": { + "version": "3.0.4", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/hash.js": { + "version": "1.1.7", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/ganache-cli/node_modules/hmac-drbg": { + "version": "1.0.1", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/ganache-cli/node_modules/inherits": { + "version": "2.0.4", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/invert-kv": { + "version": "2.0.0", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/is-hex-prefixed": { + "version": "1.0.0", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", + "dev": true, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-cli/node_modules/is-stream": { + "version": "1.1.0", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/isexe": { + "version": "2.0.0", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/keccak": { + "version": "1.4.0", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.2.1", + "inherits": "^2.0.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/ganache-cli/node_modules/lcid": { + "version": "2.0.0", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "dependencies": { + "invert-kv": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/locate-path": { + "version": "3.0.0", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/map-age-cleaner": { + "version": "0.1.3", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/md5.js": { + "version": "1.3.5", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/ganache-cli/node_modules/mem": { + "version": "4.3.0", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "dependencies": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/mimic-fn": { + "version": "2.1.0", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/minimalistic-assert": { + "version": "1.0.1", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/nan": { + "version": "2.14.0", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/nice-try": { + "version": "1.0.5", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/npm-run-path": { + "version": "2.0.2", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/once": { + "version": "1.4.0", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ganache-cli/node_modules/os-locale": { + "version": "3.1.0", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "dependencies": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/p-defer": { + "version": "1.0.0", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/p-finally": { + "version": "1.0.0", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/p-is-promise": { + "version": "2.1.0", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/p-limit": { + "version": "2.2.0", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/p-locate": { + "version": "3.0.0", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/p-try": { + "version": "2.2.0", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/path-exists": { + "version": "3.0.0", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/path-key": { + "version": "2.0.1", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-cli/node_modules/pump": { + "version": "3.0.0", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/ganache-cli/node_modules/require-directory": { + "version": "2.1.1", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/require-main-filename": { + "version": "2.0.0", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/ripemd160": { + "version": "2.0.2", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/ganache-cli/node_modules/rlp": { + "version": "2.2.3", + "integrity": "sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.1", + "safe-buffer": "^5.1.1" + }, + "bin": { + "rlp": "bin/rlp" + } + }, + "node_modules/ganache-cli/node_modules/safe-buffer": { + "version": "5.2.0", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/secp256k1": { + "version": "3.7.1", + "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "bip66": "^1.1.5", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "drbg.js": "^1.0.1", + "elliptic": "^6.4.1", + "nan": "^2.14.0", + "safe-buffer": "^5.1.2" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/ganache-cli/node_modules/semver": { + "version": "5.7.0", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-cli/node_modules/set-blocking": { + "version": "2.0.0", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/sha.js": { + "version": "2.4.11", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/ganache-cli/node_modules/shebang-command": { + "version": "1.2.0", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/shebang-regex": { + "version": "1.0.0", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/signal-exit": { + "version": "3.0.2", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/source-map": { + "version": "0.6.1", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/source-map-support": { + "version": "0.5.12", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/ganache-cli/node_modules/string-width": { + "version": "3.1.0", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/strip-ansi": { + "version": "5.2.0", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/strip-eof": { + "version": "1.0.0", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-cli/node_modules/strip-hex-prefix": { + "version": "1.0.0", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "dev": true, + "dependencies": { + "is-hex-prefixed": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-cli/node_modules/which": { + "version": "1.3.1", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/ganache-cli/node_modules/which-module": { + "version": "2.0.0", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/wrap-ansi": { + "version": "5.1.0", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-cli/node_modules/wrappy": { + "version": "1.0.2", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/ganache-cli/node_modules/y18n": { + "version": "4.0.0", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "node_modules/ganache-cli/node_modules/yargs": { + "version": "13.2.4", + "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.0" + } + }, + "node_modules/ganache-cli/node_modules/yargs-parser": { + "version": "13.1.1", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/ganache-core": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/ganache-core/-/ganache-core-2.13.1.tgz", + "integrity": "sha512-Ewg+kNcDqXtOohe7jCcP+ZUv9EMzOx2MoqOYYP3BCfxrDh3KjBXXaKK+Let7li0TghAs9lxmBgevZku35j5YzA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "3.0.0", + "async": "2.6.2", + "bip39": "2.5.0", + "cachedown": "1.0.0", + "clone": "2.1.2", + "debug": "3.2.6", + "encoding-down": "5.0.4", + "eth-sig-util": "^2.0.0", + "ethereumjs-abi": "0.6.8", + "ethereumjs-account": "3.0.0", + "ethereumjs-block": "2.2.2", + "ethereumjs-common": "1.5.0", + "ethereumjs-tx": "2.1.2", + "ethereumjs-util": "6.2.1", + "ethereumjs-vm": "4.2.0", + "heap": "0.2.6", + "keccak": "3.0.1", + "level-sublevel": "6.6.4", + "levelup": "3.1.1", + "lodash": "4.17.20", + "lru-cache": "5.1.1", + "merkle-patricia-tree": "3.0.0", + "patch-package": "6.2.2", + "seedrandom": "3.0.1", + "source-map-support": "0.5.12", + "tmp": "0.1.0", + "web3-provider-engine": "14.2.1", + "websocket": "1.0.32" + }, + "engines": { + "node": ">=8.9.0" + }, + "optionalDependencies": { + "ethereumjs-wallet": "0.6.5", + "web3": "1.2.11" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/abi": { + "version": "5.0.0-beta.153", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz", + "integrity": "sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/address": ">=5.0.0-beta.128", + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/constants": ">=5.0.0-beta.128", + "@ethersproject/hash": ">=5.0.0-beta.128", + "@ethersproject/keccak256": ">=5.0.0-beta.127", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/strings": ">=5.0.0-beta.130" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/address": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.5.tgz", + "integrity": "sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/rlp": "^5.0.3", + "bn.js": "^4.4.0" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/bignumber": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.8.tgz", + "integrity": "sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "bn.js": "^4.4.0" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/bytes": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.5.tgz", + "integrity": "sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/constants": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.5.tgz", + "integrity": "sha512-foaQVmxp2+ik9FrLUCtVrLZCj4M3Ibgkqvh+Xw/vFRSerkjVSYePApaVE5essxhoSlF1U9oXfWY09QI2AXtgKA==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bignumber": "^5.0.7" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/hash": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.5.tgz", + "integrity": "sha512-GpI80/h2HDpfNKpCZoxQJCjOQloGnlD5hM1G+tZe8FQDJhEvFjJoPDuWv+NaYjJfOciKS2Axqc4Q4WamdLoUgg==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/keccak256": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.4.tgz", + "integrity": "sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "js-sha3": "0.5.7" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/logger": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.6.tgz", + "integrity": "sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/@ethersproject/properties": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.4.tgz", + "integrity": "sha512-UdyX3GqBxFt15B0uSESdDNmhvEbK3ACdDXl2soshoPcneXuTswHDeA0LoPlnaZzhbgk4p6jqb4GMms5C26Qu6A==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/rlp": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.4.tgz", + "integrity": "sha512-5qrrZad7VTjofxSsm7Zg/7Dr4ZOln4S2CqiDdOuTv6MBKnXj0CiBojXyuDy52M8O3wxH0CyE924hXWTDV1PQWQ==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/signing-key": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.5.tgz", + "integrity": "sha512-Z1wY7JC1HVO4CvQWY2TyTTuAr8xK3bJijZw1a9G92JEmKdv1j255R/0YLBBcFTl2J65LUjtXynNJ2GbArPGi5g==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "elliptic": "6.5.3" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/strings": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.5.tgz", + "integrity": "sha512-JED6WaIV00xM/gvj8vSnd+0VWtDYdidTmavFRCTQakqfz+4tDo6Jz5LHgG+dd45h7ah7ykCHW0C7ZXWEDROCXQ==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "node_modules/ganache-core/node_modules/@ethersproject/transactions": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.6.tgz", + "integrity": "sha512-htsFhOD+NMBxx676A8ehSuwVV49iqpSB+CkjPZ02tpNew0K6p8g0CZ46Z1ZP946gIHAU80xQ0NACHYrjIUaCFA==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/rlp": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4" + } + }, + "node_modules/ganache-core/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "optional": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ganache-core/node_modules/@types/node": { + "version": "14.11.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.8.tgz", + "integrity": "sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/@types/pbkdf2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", + "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ganache-core/node_modules/@types/secp256k1": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", + "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ganache-core/node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/abstract-leveldown": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz", + "integrity": "sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "optional": true, + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/aes-js": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", + "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ajv": { + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/ganache-core/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/ganache-core/node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ganache-core/node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ganache-core/node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.11" + } + }, + "node_modules/ganache-core/node_modules/async-eventemitter": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", + "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", + "dev": true, + "dependencies": { + "async": "^2.4.0" + } + }, + "node_modules/ganache-core/node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/ganache-core/node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/ganache-core/node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/aws4": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "dependencies": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ganache-core/node_modules/babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "dependencies": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + } + }, + "node_modules/ganache-core/node_modules/babel-core/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/babel-core/node_modules/json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/ganache-core/node_modules/babel-core/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-core/node_modules/slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "dependencies": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/babel-generator/node_modules/jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "dependencies": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "dependencies": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "dependencies": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "dependencies": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "dependencies": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "dependencies": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "dependencies": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "dependencies": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "dependencies": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "dependencies": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "dev": true, + "dependencies": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "dependencies": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "dependencies": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "dependencies": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "dependencies": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "dependencies": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "dependencies": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "dependencies": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "dependencies": { + "regenerator-transform": "^0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/ganache-core/node_modules/babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true, + "dependencies": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + } + }, + "node_modules/ganache-core/node_modules/babel-preset-env/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "dependencies": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + } + }, + "node_modules/ganache-core/node_modules/babel-register/node_modules/source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/ganache-core/node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/ganache-core/node_modules/babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "node_modules/ganache-core/node_modules/babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "dependencies": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "node_modules/ganache-core/node_modules/babel-traverse/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/babel-traverse/node_modules/globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babel-traverse/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/ganache-core/node_modules/babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "node_modules/ganache-core/node_modules/babel-types/node_modules/to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/babelify": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", + "dev": true, + "dependencies": { + "babel-core": "^6.0.14", + "object-assign": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true, + "bin": { + "babylon": "bin/babylon.js" + } + }, + "node_modules/ganache-core/node_modules/backoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", + "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", + "dev": true, + "dependencies": { + "precond": "0.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "node_modules/ganache-core/node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/base-x": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", + "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ganache-core/node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/ganache-core/node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/ganache-core/node_modules/bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", + "dev": true, + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/bip39": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-2.5.0.tgz", + "integrity": "sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.0", + "pbkdf2": "^3.0.9", + "randombytes": "^2.0.1", + "safe-buffer": "^5.0.1", + "unorm": "^1.3.3" + } + }, + "node_modules/ganache-core/node_modules/blakejs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", + "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=", + "dev": true + }, + "node_modules/ganache-core/node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "optional": true, + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/body-parser/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ganache-core/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/ganache-core/node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ganache-core/node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "optional": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "optional": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/ganache-core/node_modules/browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/ganache-core/node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/ganache-core/node_modules/browserify-sign/node_modules/bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/browserify-sign/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ganache-core/node_modules/browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + }, + "bin": { + "browserslist": "cli.js" + } + }, + "node_modules/ganache-core/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "dev": true, + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/ganache-core/node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/ganache-core/node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dev": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/ganache-core/node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/ganache-core/node_modules/buffer-to-arraybuffer": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", + "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "node_modules/ganache-core/node_modules/bufferutil": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", + "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "~3.7.0" + } + }, + "node_modules/ganache-core/node_modules/bufferutil/node_modules/node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/ganache-core/node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/bytewise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", + "integrity": "sha1-HRPL/3F65xWAlKqIGzXQgbOHJT4=", + "dev": true, + "dependencies": { + "bytewise-core": "^1.2.2", + "typewise": "^1.0.3" + } + }, + "node_modules/ganache-core/node_modules/bytewise-core": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz", + "integrity": "sha1-P7QQx+kVWOsasiqCg0V3qmvWHUI=", + "dev": true, + "dependencies": { + "typewise-core": "^1.2" + } + }, + "node_modules/ganache-core/node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "optional": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ganache-core/node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ganache-core/node_modules/cachedown": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cachedown/-/cachedown-1.0.0.tgz", + "integrity": "sha1-1D8DbkUQaWsxJG19sx6/D3rDLRU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "^2.4.1", + "lru-cache": "^3.2.0" + } + }, + "node_modules/ganache-core/node_modules/cachedown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/cachedown/node_modules/lru-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", + "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/caniuse-lite": { + "version": "1.0.30001146", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001146.tgz", + "integrity": "sha512-VAy5RHDfTJhpxnDdp2n40GPPLp3KqNrXz1QqFv4J64HvArKs8nuNMOWkB3ICOaBTU/Aj4rYAo/ytdQDDFF/Pug==", + "dev": true + }, + "node_modules/ganache-core/node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "node_modules/ganache-core/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/checkpoint-store": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz", + "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", + "dev": true, + "dependencies": { + "functional-red-black-tree": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/cids": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", + "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", + "dev": true, + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "class-is": "^1.1.0", + "multibase": "~0.6.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.15" + }, + "engines": { + "node": ">=4.0.0", + "npm": ">=3.0.0" + } + }, + "node_modules/ganache-core/node_modules/cids/node_modules/multicodec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", + "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", + "dev": true, + "optional": true, + "dependencies": { + "buffer": "^5.6.0", + "varint": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ganache-core/node_modules/class-is": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", + "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/class-utils/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ganache-core/node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "optional": true, + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ganache-core/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/ganache-core/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/ganache-core/node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "optional": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/content-hash": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", + "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", + "dev": true, + "optional": true, + "dependencies": { + "cids": "^0.7.1", + "multicodec": "^0.5.5", + "multihashes": "^0.4.15" + } + }, + "node_modules/ganache-core/node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/ganache-core/node_modules/convert-source-map/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true, + "hasInstallScript": true + }, + "node_modules/ganache-core/node_modules/core-js-pure": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", + "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==", + "dev": true, + "hasInstallScript": true + }, + "node_modules/ganache-core/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/ganache-core/node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "optional": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ganache-core/node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/ganache-core/node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/ganache-core/node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/ganache-core/node_modules/cross-fetch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.3.tgz", + "integrity": "sha512-PrWWNH3yL2NYIb/7WF/5vFG3DCQiXDOVf8k3ijatbrtnwNuhMWLC7YF7uqf53tbTFDzHIUD8oITw4Bxt8ST3Nw==", + "dev": true, + "dependencies": { + "node-fetch": "2.1.2", + "whatwg-fetch": "2.0.4" + } + }, + "node_modules/ganache-core/node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "optional": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/ganache-core/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/ganache-core/node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/ganache-core/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "optional": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "dependencies": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "node_modules/ganache-core/node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/deferred-leveldown": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", + "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~5.0.0", + "inherits": "^2.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/deferred-leveldown/node_modules/abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ganache-core/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "optional": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "dependencies": { + "repeating": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/ganache-core/node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/dotignore": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz", + "integrity": "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.4" + }, + "bin": { + "ignored": "bin/ignored" + } + }, + "node_modules/ganache-core/node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ganache-core/node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/electron-to-chromium": { + "version": "1.3.578", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.578.tgz", + "integrity": "sha512-z4gU6dA1CbBJsAErW5swTGAaU2TBzc2mPAonJb00zqW1rOraDo2zfBMDRvaz9cVic+0JEZiYbHWPw/fTaZlG2Q==", + "dev": true + }, + "node_modules/ganache-core/node_modules/elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/ganache-core/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/ganache-core/node_modules/encoding-down": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", + "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", + "dev": true, + "dependencies": { + "abstract-leveldown": "^5.0.0", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0", + "xtend": "^4.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/encoding-down/node_modules/abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/ganache-core/node_modules/errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/ganache-core/node_modules/es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "dependencies": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "node_modules/ganache-core/node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/ganache-core/node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/ganache-core/node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ganache-core/node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/eth-block-tracker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz", + "integrity": "sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug==", + "dev": true, + "dependencies": { + "eth-query": "^2.1.0", + "ethereumjs-tx": "^1.3.3", + "ethereumjs-util": "^5.1.3", + "ethjs-util": "^0.1.3", + "json-rpc-engine": "^3.6.0", + "pify": "^2.3.0", + "tape": "^4.6.3" + } + }, + "node_modules/ganache-core/node_modules/eth-block-tracker/node_modules/ethereumjs-tx": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", + "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", + "dev": true, + "dependencies": { + "ethereum-common": "^0.0.18", + "ethereumjs-util": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-block-tracker/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-block-tracker/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/eth-ens-namehash": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", + "integrity": "sha1-IprEbsqG1S4MmR58sq74P/D2i88=", + "dev": true, + "optional": true, + "dependencies": { + "idna-uts46-hx": "^2.3.1", + "js-sha3": "^0.5.7" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-infura": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz", + "integrity": "sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw==", + "dev": true, + "dependencies": { + "cross-fetch": "^2.1.1", + "eth-json-rpc-middleware": "^1.5.0", + "json-rpc-engine": "^3.4.0", + "json-rpc-error": "^2.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz", + "integrity": "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==", + "dev": true, + "dependencies": { + "async": "^2.5.0", + "eth-query": "^2.1.2", + "eth-tx-summary": "^3.1.2", + "ethereumjs-block": "^1.6.0", + "ethereumjs-tx": "^1.3.3", + "ethereumjs-util": "^5.1.2", + "ethereumjs-vm": "^2.1.0", + "fetch-ponyfill": "^4.0.0", + "json-rpc-engine": "^3.6.0", + "json-rpc-error": "^2.0.0", + "json-stable-stringify": "^1.0.1", + "promise-to-callback": "^1.0.0", + "tape": "^4.6.3" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.6.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-account": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", + "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", + "dev": true, + "dependencies": { + "ethereumjs-util": "^5.0.0", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-block": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "^1.2.2", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-block/node_modules/ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-tx": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", + "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", + "dev": true, + "dependencies": { + "ethereum-common": "^0.0.18", + "ethereumjs-util": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz", + "integrity": "sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "async-eventemitter": "^0.2.2", + "ethereumjs-account": "^2.0.3", + "ethereumjs-block": "~2.2.0", + "ethereumjs-common": "^1.1.0", + "ethereumjs-util": "^6.0.0", + "fake-merkle-patricia-tree": "^1.0.1", + "functional-red-black-tree": "^1.0.1", + "merkle-patricia-tree": "^2.3.2", + "rustbn.js": "~0.2.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm/node_modules/ethereumjs-block": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", + "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm/node_modules/ethereumjs-block/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm/node_modules/ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "dev": true, + "dependencies": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-ws/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-ws/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-lib": { + "version": "0.1.29", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz", + "integrity": "sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "nano-json-stream-parser": "^0.1.2", + "servify": "^0.1.12", + "ws": "^3.0.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/ganache-core/node_modules/eth-query": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz", + "integrity": "sha1-1nQdkAAQa1FRDHLbktY2VFam2l4=", + "dev": true, + "dependencies": { + "json-rpc-random-id": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "node_modules/ganache-core/node_modules/eth-sig-util": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.3.0.tgz", + "integrity": "sha512-ugD1AvaggvKaZDgnS19W5qOfepjGc7qHrt7TrAaL54gJw9SHvgIXJ3r2xOMW30RWJZNP+1GlTOy5oye7yXA4xA==", + "dev": true, + "dependencies": { + "buffer": "^5.2.1", + "elliptic": "^6.4.0", + "ethereumjs-abi": "0.6.5", + "ethereumjs-util": "^5.1.1", + "tweetnacl": "^1.0.0", + "tweetnacl-util": "^0.15.0" + } + }, + "node_modules/ganache-core/node_modules/eth-sig-util/node_modules/ethereumjs-abi": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz", + "integrity": "sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=", + "dev": true, + "dependencies": { + "bn.js": "^4.10.0", + "ethereumjs-util": "^4.3.0" + } + }, + "node_modules/ganache-core/node_modules/eth-sig-util/node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz", + "integrity": "sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w==", + "dev": true, + "dependencies": { + "bn.js": "^4.8.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-sig-util/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz", + "integrity": "sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "clone": "^2.0.0", + "concat-stream": "^1.5.1", + "end-of-stream": "^1.1.0", + "eth-query": "^2.0.2", + "ethereumjs-block": "^1.4.1", + "ethereumjs-tx": "^1.1.1", + "ethereumjs-util": "^5.0.1", + "ethereumjs-vm": "^2.6.0", + "through2": "^2.0.3" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.6.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-account": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", + "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", + "dev": true, + "dependencies": { + "ethereumjs-util": "^5.0.0", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-block": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "^1.2.2", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-block/node_modules/ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-tx": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", + "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", + "dev": true, + "dependencies": { + "ethereum-common": "^0.0.18", + "ethereumjs-util": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz", + "integrity": "sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "async-eventemitter": "^0.2.2", + "ethereumjs-account": "^2.0.3", + "ethereumjs-block": "~2.2.0", + "ethereumjs-common": "^1.1.0", + "ethereumjs-util": "^6.0.0", + "fake-merkle-patricia-tree": "^1.0.1", + "functional-red-black-tree": "^1.0.1", + "merkle-patricia-tree": "^2.3.2", + "rustbn.js": "~0.2.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm/node_modules/ethereumjs-block": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", + "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm/node_modules/ethereumjs-block/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm/node_modules/ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "dev": true, + "dependencies": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-ws/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-ws/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethashjs": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ethashjs/-/ethashjs-0.0.8.tgz", + "integrity": "sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "buffer-xor": "^2.0.1", + "ethereumjs-util": "^7.0.2", + "miller-rabin": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethashjs/node_modules/bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethashjs/node_modules/buffer-xor": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", + "integrity": "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethashjs/node_modules/ethereumjs-util": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.6.tgz", + "integrity": "sha512-E9aJ9W7XZkcBqIblfstBU+0nGSjF9Dz/Ps7s1NTFOgDZM8pwD+nX1P1GBJeSqB6Osxhj2UtuxVCqjvmrj2svzw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereum-bloom-filters": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.7.tgz", + "integrity": "sha512-cDcJJSJ9GMAcURiAWO3DxIEhTL/uWqlQnvgKpuYQzYPrt/izuGU+1ntQmHt0IRq6ADoSYHFnB+aCEFIldjhkMQ==", + "dev": true, + "optional": true, + "dependencies": { + "js-sha3": "^0.8.0" + } + }, + "node_modules/ganache-core/node_modules/ethereum-bloom-filters/node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ethereum-common": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", + "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-abi": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", + "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-account": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz", + "integrity": "sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA==", + "dev": true, + "dependencies": { + "ethereumjs-util": "^6.0.0", + "rlp": "^2.2.1", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", + "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.6.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-ws/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-ws/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-blockchain": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz", + "integrity": "sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ==", + "dev": true, + "dependencies": { + "async": "^2.6.1", + "ethashjs": "~0.0.7", + "ethereumjs-block": "~2.2.2", + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.1.0", + "flow-stoplight": "^1.0.0", + "level-mem": "^3.0.1", + "lru-cache": "^5.1.1", + "rlp": "^2.2.2", + "semaphore": "^1.1.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-common": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz", + "integrity": "sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "dev": true, + "dependencies": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz", + "integrity": "sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "async-eventemitter": "^0.2.2", + "core-js-pure": "^3.0.1", + "ethereumjs-account": "^3.0.0", + "ethereumjs-block": "^2.2.2", + "ethereumjs-blockchain": "^4.0.3", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.2", + "ethereumjs-util": "^6.2.0", + "fake-merkle-patricia-tree": "^1.0.1", + "functional-red-black-tree": "^1.0.1", + "merkle-patricia-tree": "^2.3.2", + "rustbn.js": "~0.2.0", + "safe-buffer": "^5.1.1", + "util.promisify": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.6.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-ws/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-ws/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ethereumjs-wallet": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz", + "integrity": "sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA==", + "dev": true, + "optional": true, + "dependencies": { + "aes-js": "^3.1.1", + "bs58check": "^2.1.2", + "ethereum-cryptography": "^0.1.3", + "ethereumjs-util": "^6.0.0", + "randombytes": "^2.0.6", + "safe-buffer": "^5.1.2", + "scryptsy": "^1.2.1", + "utf8": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "node_modules/ganache-core/node_modules/ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-core/node_modules/ethjs-unit/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dev": true, + "dependencies": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-core/node_modules/eventemitter3": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", + "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/ganache-core/node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/ganache-core/node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "optional": true, + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/ganache-core/node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/express/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ganache-core/node_modules/express/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "dependencies": { + "type": "^2.0.0" + } + }, + "node_modules/ganache-core/node_modules/ext/node_modules/type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/extglob/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/ganache-core/node_modules/fake-merkle-patricia-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz", + "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", + "dev": true, + "dependencies": { + "checkpoint-store": "^1.1.0" + } + }, + "node_modules/ganache-core/node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/ganache-core/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/fetch-ponyfill": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz", + "integrity": "sha1-rjzl9zLGReq4fkroeTQUcJsjmJM=", + "dev": true, + "dependencies": { + "node-fetch": "~1.7.1" + } + }, + "node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "dev": true, + "dependencies": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "optional": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz", + "integrity": "sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==", + "dev": true, + "dependencies": { + "fs-extra": "^4.0.3", + "micromatch": "^3.1.4" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/flow-stoplight": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz", + "integrity": "sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s=", + "dev": true + }, + "node_modules/ganache-core/node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/ganache-core/node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/ganache-core/node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/ganache-core/node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/ganache-core/node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/ganache-core/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "optional": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ganache-core/node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "dev": true, + "dependencies": { + "min-document": "^2.19.0", + "process": "~0.5.1" + } + }, + "node_modules/ganache-core/node_modules/global/node_modules/process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/ganache-core/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "optional": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/ganache-core/node_modules/got/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "optional": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/ganache-core/node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "dev": true, + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dev": true, + "optional": true, + "dependencies": { + "has-symbol-support-x": "^1.4.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/has-values/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/has-values/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/has-values/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ganache-core/node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/heap": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", + "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=", + "dev": true + }, + "node_modules/ganache-core/node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "optional": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/http-errors/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/http-https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", + "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/ganache-core/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/idna-uts46-hx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", + "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", + "dev": true, + "optional": true, + "dependencies": { + "punycode": "2.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/ganache-core/node_modules/idna-uts46-hx/node_modules/punycode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", + "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", + "dev": true + }, + "node_modules/ganache-core/node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/ganache-core/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ganache-core/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/ganache-core/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-fn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fn/-/is-fn-1.0.0.tgz", + "integrity": "sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", + "dev": true, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-core/node_modules/is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/ganache-core/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/ganache-core/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true, + "optional": true, + "dependencies": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ganache-core/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/json-rpc-engine": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz", + "integrity": "sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "babel-preset-env": "^1.7.0", + "babelify": "^7.3.0", + "json-rpc-error": "^2.0.0", + "promise-to-callback": "^1.0.0", + "safe-event-emitter": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/json-rpc-error": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-rpc-error/-/json-rpc-error-2.0.0.tgz", + "integrity": "sha1-p6+cICg4tekFxyUOVH8a/3cligI=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1" + } + }, + "node_modules/ganache-core/node_modules/json-rpc-random-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz", + "integrity": "sha1-uknZat7RRE27jaPSA3SKy7zeyMg=", + "dev": true + }, + "node_modules/ganache-core/node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "dependencies": { + "jsonify": "~0.0.0" + } + }, + "node_modules/ganache-core/node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/ganache-core/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/ganache-core/node_modules/jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/ganache-core/node_modules/keccak": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", + "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ganache-core/node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "optional": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/ganache-core/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, + "node_modules/ganache-core/node_modules/level-codec": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", + "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", + "dev": true, + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/level-iterator-stream": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz", + "integrity": "sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.5", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/level-mem": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-3.0.1.tgz", + "integrity": "sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg==", + "dev": true, + "dependencies": { + "level-packager": "~4.0.0", + "memdown": "~3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/level-mem/node_modules/abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/level-mem/node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/level-mem/node_modules/memdown": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz", + "integrity": "sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~5.0.0", + "functional-red-black-tree": "~1.0.1", + "immediate": "~3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/level-mem/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/level-packager": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-4.0.1.tgz", + "integrity": "sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q==", + "dev": true, + "dependencies": { + "encoding-down": "~5.0.0", + "levelup": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/level-post": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/level-post/-/level-post-1.0.7.tgz", + "integrity": "sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew==", + "dev": true, + "dependencies": { + "ltgt": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/level-sublevel": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/level-sublevel/-/level-sublevel-6.6.4.tgz", + "integrity": "sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA==", + "dev": true, + "dependencies": { + "bytewise": "~1.1.0", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0", + "level-iterator-stream": "^2.0.3", + "ltgt": "~2.1.1", + "pull-defer": "^0.2.2", + "pull-level": "^2.0.3", + "pull-stream": "^3.6.8", + "typewiselite": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/level-ws": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-1.0.0.tgz", + "integrity": "sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.2.8", + "xtend": "^4.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/levelup": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz", + "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~4.0.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~3.0.0", + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/levelup/node_modules/level-iterator-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", + "integrity": "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/looper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/looper/-/looper-2.0.0.tgz", + "integrity": "sha1-Zs0Md0rz1P7axTeU90LbVtqPCew=", + "dev": true + }, + "node_modules/ganache-core/node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/ganache-core/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/ganache-core/node_modules/ltgt": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.1.3.tgz", + "integrity": "sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ=", + "dev": true + }, + "node_modules/ganache-core/node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/ganache-core/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/merkle-patricia-tree": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz", + "integrity": "sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ==", + "dev": true, + "dependencies": { + "async": "^2.6.1", + "ethereumjs-util": "^5.2.0", + "level-mem": "^3.0.1", + "level-ws": "^1.0.0", + "readable-stream": "^3.0.6", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ganache-core/node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/merkle-patricia-tree/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ganache-core/node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/ganache-core/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "dependencies": { + "mime-db": "1.44.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "dev": true, + "dependencies": { + "dom-walk": "^0.1.0" + } + }, + "node_modules/ganache-core/node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/ganache-core/node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "optional": true, + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/ganache-core/node_modules/minizlib/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "optional": true, + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/ganache-core/node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ganache-core/node_modules/mkdirp-promise": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", + "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", + "dev": true, + "optional": true, + "dependencies": { + "mkdirp": "*" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/mock-fs": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.13.0.tgz", + "integrity": "sha512-DD0vOdofJdoaRNtnWcrXe6RQbpHkPPmtqGq14uRX0F8ZKJ5nv89CVTYl/BZdppDxBDaV0hl75htg3abpEWlPZA==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/multibase": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", + "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", + "dev": true, + "optional": true, + "dependencies": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + }, + "node_modules/ganache-core/node_modules/multicodec": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", + "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", + "dev": true, + "optional": true, + "dependencies": { + "varint": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/multihashes": { + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", + "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", + "dev": true, + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "multibase": "^0.7.0", + "varint": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/multihashes/node_modules/multibase": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", + "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", + "dev": true, + "optional": true, + "dependencies": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + }, + "node_modules/ganache-core/node_modules/nano-json-stream-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", + "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node_modules/ganache-core/node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/node-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", + "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", + "dev": true, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/ganache-core/node_modules/node-gyp-build": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/ganache-core/node_modules/normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ganache-core/node_modules/number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-core/node_modules/number-to-bn/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/object-is": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", + "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/object-is/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/object.assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/object.assign/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/oboe": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.4.tgz", + "integrity": "sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY=", + "dev": true, + "optional": true, + "dependencies": { + "http-https": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "optional": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ganache-core/node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "dev": true, + "optional": true, + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/p-timeout/node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "optional": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/parse-headers": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", + "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/patch-package": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.2.2.tgz", + "integrity": "sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg==", + "dev": true, + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "find-yarn-workspace-root": "^1.2.1", + "fs-extra": "^7.0.1", + "is-ci": "^2.0.0", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.0", + "rimraf": "^2.6.3", + "semver": "^5.6.0", + "slash": "^2.0.0", + "tmp": "^0.0.33" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "npm": ">5" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/ganache-core/node_modules/patch-package/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/ganache-core/node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/ganache-core/node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "node_modules/ganache-core/node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/precond": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", + "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true, + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/ganache-core/node_modules/promise-to-callback": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/promise-to-callback/-/promise-to-callback-1.0.0.tgz", + "integrity": "sha1-XSp0kBC/tn2WNZj805YHRqaP7vc=", + "dev": true, + "dependencies": { + "is-fn": "^1.0.0", + "set-immediate-shim": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "optional": true, + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ganache-core/node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "node_modules/ganache-core/node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/ganache-core/node_modules/pull-cat": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/pull-cat/-/pull-cat-1.1.11.tgz", + "integrity": "sha1-tkLdElXaN2pwa220+pYvX9t0wxs=", + "dev": true + }, + "node_modules/ganache-core/node_modules/pull-defer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/pull-defer/-/pull-defer-0.2.3.tgz", + "integrity": "sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/pull-level": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pull-level/-/pull-level-2.0.4.tgz", + "integrity": "sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg==", + "dev": true, + "dependencies": { + "level-post": "^1.0.7", + "pull-cat": "^1.1.9", + "pull-live": "^1.0.1", + "pull-pushable": "^2.0.0", + "pull-stream": "^3.4.0", + "pull-window": "^2.1.4", + "stream-to-pull-stream": "^1.7.1" + } + }, + "node_modules/ganache-core/node_modules/pull-live": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pull-live/-/pull-live-1.0.1.tgz", + "integrity": "sha1-pOzuAeMwFV6RJLu89HYfIbOPUfU=", + "dev": true, + "dependencies": { + "pull-cat": "^1.1.9", + "pull-stream": "^3.4.0" + } + }, + "node_modules/ganache-core/node_modules/pull-pushable": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pull-pushable/-/pull-pushable-2.2.0.tgz", + "integrity": "sha1-Xy867UethpGfAbEqLpnW8b13ZYE=", + "dev": true + }, + "node_modules/ganache-core/node_modules/pull-stream": { + "version": "3.6.14", + "resolved": "https://registry.npmjs.org/pull-stream/-/pull-stream-3.6.14.tgz", + "integrity": "sha512-KIqdvpqHHaTUA2mCYcLG1ibEbu/LCKoJZsBWyv9lSYtPkJPBq8m3Hxa103xHi6D2thj5YXa0TqK3L3GUkwgnew==", + "dev": true + }, + "node_modules/ganache-core/node_modules/pull-window": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/pull-window/-/pull-window-2.1.4.tgz", + "integrity": "sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA=", + "dev": true, + "dependencies": { + "looper": "^2.0.0" + } + }, + "node_modules/ganache-core/node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/ganache-core/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ganache-core/node_modules/query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "optional": true, + "dependencies": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/ganache-core/node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "optional": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/ganache-core/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "optional": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/ganache-core/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/regenerate": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", + "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", + "dev": true + }, + "node_modules/ganache-core/node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "dependencies": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + }, + "node_modules/ganache-core/node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "dependencies": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "node_modules/ganache-core/node_modules/regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "node_modules/ganache-core/node_modules/regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/ganache-core/node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/ganache-core/node_modules/repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/ganache-core/node_modules/repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "dependencies": { + "is-finite": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ganache-core/node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + } + }, + "node_modules/ganache-core/node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "optional": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "dependencies": { + "through": "~2.3.4" + } + }, + "node_modules/ganache-core/node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/ganache-core/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ganache-core/node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/ganache-core/node_modules/rlp": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", + "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.1" + }, + "bin": { + "rlp": "bin/rlp" + } + }, + "node_modules/ganache-core/node_modules/rustbn.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", + "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/safe-event-emitter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz", + "integrity": "sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg==", + "dev": true, + "dependencies": { + "events": "^3.0.0" + } + }, + "node_modules/ganache-core/node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/ganache-core/node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/scryptsy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", + "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", + "dev": true, + "optional": true, + "dependencies": { + "pbkdf2": "^3.0.3" + } + }, + "node_modules/ganache-core/node_modules/secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ganache-core/node_modules/seedrandom": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.1.tgz", + "integrity": "sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ganache-core/node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "optional": true, + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ganache-core/node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "optional": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ganache-core/node_modules/servify": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", + "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "dev": true, + "optional": true, + "dependencies": { + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "request": "^2.79.0", + "xhr": "^2.3.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/set-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/ganache-core/node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "dev": true, + "optional": true, + "dependencies": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon-util/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/ganache-core/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/ganache-core/node_modules/source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/ganache-core/node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "node_modules/ganache-core/node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/sshpk/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/ganache-core/node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/static-extend/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/stream-to-pull-stream": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz", + "integrity": "sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg==", + "dev": true, + "dependencies": { + "looper": "^3.0.0", + "pull-stream": "^3.2.3" + } + }, + "node_modules/ganache-core/node_modules/stream-to-pull-stream/node_modules/looper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/looper/-/looper-3.0.0.tgz", + "integrity": "sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k=", + "dev": true + }, + "node_modules/ganache-core/node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/ganache-core/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/string.prototype.trim": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.2.tgz", + "integrity": "sha512-b5yrbl3BXIjHau9Prk7U0RRYcUYdN4wGSVaqoBQS50CCE3KBuYU0TYRNPFCP7aVoNMX87HKThdMRVIP3giclKg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/string.prototype.trim/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/ganache-core/node_modules/string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/ganache-core/node_modules/strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "dev": true, + "dependencies": { + "is-hex-prefixed": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ganache-core/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/swarm-js": { + "version": "0.1.40", + "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.40.tgz", + "integrity": "sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA==", + "dev": true, + "optional": true, + "dependencies": { + "bluebird": "^3.5.0", + "buffer": "^5.0.5", + "eth-lib": "^0.1.26", + "fs-extra": "^4.0.2", + "got": "^7.1.0", + "mime-types": "^2.1.16", + "mkdirp-promise": "^5.0.1", + "mock-fs": "^4.1.0", + "setimmediate": "^1.0.5", + "tar": "^4.0.2", + "xhr-request": "^1.0.1" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "optional": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true, + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "dev": true, + "optional": true, + "dependencies": { + "decompress-response": "^3.2.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-plain-obj": "^1.1.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "p-cancelable": "^0.3.0", + "p-timeout": "^1.1.1", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "url-parse-lax": "^1.0.0", + "url-to-options": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", + "dev": true, + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/swarm-js/node_modules/url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "optional": true, + "dependencies": { + "prepend-http": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/tape": { + "version": "4.13.3", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.13.3.tgz", + "integrity": "sha512-0/Y20PwRIUkQcTCSi4AASs+OANZZwqPKaipGCEwp10dQMipVvSZwUUCi01Y/OklIGyHKFhIcjock+DKnBfLAFw==", + "dev": true, + "dependencies": { + "deep-equal": "~1.1.1", + "defined": "~1.0.0", + "dotignore": "~0.1.2", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.6", + "has": "~1.0.3", + "inherits": "~2.0.4", + "is-regex": "~1.0.5", + "minimist": "~1.2.5", + "object-inspect": "~1.7.0", + "resolve": "~1.17.0", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.2.1", + "through": "~2.3.8" + }, + "bin": { + "tape": "bin/tape" + } + }, + "node_modules/ganache-core/node_modules/tape/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/tape/node_modules/is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ganache-core/node_modules/tape/node_modules/object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/ganache-core/node_modules/tar/node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "optional": true, + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/ganache-core/node_modules/tar/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "optional": true, + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/ganache-core/node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/ganache-core/node_modules/timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/tmp": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", + "dev": true, + "dependencies": { + "rimraf": "^2.6.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/to-object-path/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/ganache-core/node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache-core/node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ganache-core/node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ganache-core/node_modules/trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ganache-core/node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/tweetnacl-util": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", + "dev": true + }, + "node_modules/ganache-core/node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "node_modules/ganache-core/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "optional": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ganache-core/node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/ganache-core/node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/ganache-core/node_modules/typewise": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz", + "integrity": "sha1-EGeTZUCvl5N8xdz5kiSG6fooRlE=", + "dev": true, + "dependencies": { + "typewise-core": "^1.2.0" + } + }, + "node_modules/ganache-core/node_modules/typewise-core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz", + "integrity": "sha1-l+uRgFx/VdL5QXSPpQ0xXZke8ZU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/typewiselite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typewiselite/-/typewiselite-1.0.0.tgz", + "integrity": "sha1-yIgvobsQksBgBal/NO9chQjjZk4=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/union-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/ganache-core/node_modules/unorm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", + "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/ganache-core/node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/ganache-core/node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "node_modules/ganache-core/node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "optional": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache-core/node_modules/url-set-query": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", + "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ganache-core/node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ganache-core/node_modules/utf-8-validate": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz", + "integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "~3.7.0" + } + }, + "node_modules/ganache-core/node_modules/utf-8-validate/node_modules/node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/ganache-core/node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "node_modules/ganache-core/node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/ganache-core/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/ganache-core/node_modules/varint": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", + "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ganache-core/node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/ganache-core/node_modules/web3": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.11.tgz", + "integrity": "sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "dependencies": { + "web3-bzz": "1.2.11", + "web3-core": "1.2.11", + "web3-eth": "1.2.11", + "web3-eth-personal": "1.2.11", + "web3-net": "1.2.11", + "web3-shh": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-bzz": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.11.tgz", + "integrity": "sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "^12.12.6", + "got": "9.6.0", + "swarm-js": "^0.1.40", + "underscore": "1.9.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-bzz/node_modules/@types/node": { + "version": "12.12.67", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz", + "integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/web3-core": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.11.tgz", + "integrity": "sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ==", + "dev": true, + "optional": true, + "dependencies": { + "@types/bn.js": "^4.11.5", + "@types/node": "^12.12.6", + "bignumber.js": "^9.0.0", + "web3-core-helpers": "1.2.11", + "web3-core-method": "1.2.11", + "web3-core-requestmanager": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-core-helpers": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz", + "integrity": "sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A==", + "dev": true, + "optional": true, + "dependencies": { + "underscore": "1.9.1", + "web3-eth-iban": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-core-method": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.11.tgz", + "integrity": "sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/transactions": "^5.0.0-beta.135", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.11", + "web3-core-promievent": "1.2.11", + "web3-core-subscriptions": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-core-promievent": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz", + "integrity": "sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA==", + "dev": true, + "optional": true, + "dependencies": { + "eventemitter3": "4.0.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-core-requestmanager": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz", + "integrity": "sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA==", + "dev": true, + "optional": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.11", + "web3-providers-http": "1.2.11", + "web3-providers-ipc": "1.2.11", + "web3-providers-ws": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-core-subscriptions": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz", + "integrity": "sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg==", + "dev": true, + "optional": true, + "dependencies": { + "eventemitter3": "4.0.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-core/node_modules/@types/node": { + "version": "12.12.67", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz", + "integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/web3-eth": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.11.tgz", + "integrity": "sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ==", + "dev": true, + "optional": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core": "1.2.11", + "web3-core-helpers": "1.2.11", + "web3-core-method": "1.2.11", + "web3-core-subscriptions": "1.2.11", + "web3-eth-abi": "1.2.11", + "web3-eth-accounts": "1.2.11", + "web3-eth-contract": "1.2.11", + "web3-eth-ens": "1.2.11", + "web3-eth-iban": "1.2.11", + "web3-eth-personal": "1.2.11", + "web3-net": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-abi": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz", + "integrity": "sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg==", + "dev": true, + "optional": true, + "dependencies": { + "@ethersproject/abi": "5.0.0-beta.153", + "underscore": "1.9.1", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-accounts": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz", + "integrity": "sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw==", + "dev": true, + "optional": true, + "dependencies": { + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.8", + "ethereumjs-common": "^1.3.2", + "ethereumjs-tx": "^2.1.1", + "scrypt-js": "^3.0.1", + "underscore": "1.9.1", + "uuid": "3.3.2", + "web3-core": "1.2.11", + "web3-core-helpers": "1.2.11", + "web3-core-method": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-accounts/node_modules/eth-lib": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-accounts/node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true, + "optional": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-contract": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz", + "integrity": "sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow==", + "dev": true, + "optional": true, + "dependencies": { + "@types/bn.js": "^4.11.5", + "underscore": "1.9.1", + "web3-core": "1.2.11", + "web3-core-helpers": "1.2.11", + "web3-core-method": "1.2.11", + "web3-core-promievent": "1.2.11", + "web3-core-subscriptions": "1.2.11", + "web3-eth-abi": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-ens": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz", + "integrity": "sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA==", + "dev": true, + "optional": true, + "dependencies": { + "content-hash": "^2.5.2", + "eth-ens-namehash": "2.0.8", + "underscore": "1.9.1", + "web3-core": "1.2.11", + "web3-core-helpers": "1.2.11", + "web3-core-promievent": "1.2.11", + "web3-eth-abi": "1.2.11", + "web3-eth-contract": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-iban": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz", + "integrity": "sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.11.9", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-personal": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz", + "integrity": "sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "^12.12.6", + "web3-core": "1.2.11", + "web3-core-helpers": "1.2.11", + "web3-core-method": "1.2.11", + "web3-net": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-eth-personal/node_modules/@types/node": { + "version": "12.12.67", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz", + "integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/web3-net": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.11.tgz", + "integrity": "sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg==", + "dev": true, + "optional": true, + "dependencies": { + "web3-core": "1.2.11", + "web3-core-method": "1.2.11", + "web3-utils": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz", + "integrity": "sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw==", + "dev": true, + "dependencies": { + "async": "^2.5.0", + "backoff": "^2.5.0", + "clone": "^2.0.0", + "cross-fetch": "^2.1.0", + "eth-block-tracker": "^3.0.0", + "eth-json-rpc-infura": "^3.1.0", + "eth-sig-util": "^1.4.2", + "ethereumjs-block": "^1.2.2", + "ethereumjs-tx": "^1.2.0", + "ethereumjs-util": "^5.1.5", + "ethereumjs-vm": "^2.3.4", + "json-rpc-error": "^2.0.0", + "json-stable-stringify": "^1.0.1", + "promise-to-callback": "^1.0.0", + "readable-stream": "^2.2.9", + "request": "^2.85.0", + "semaphore": "^1.0.3", + "ws": "^5.1.1", + "xhr": "^2.2.0", + "xtend": "^4.0.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.6.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/eth-sig-util": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz", + "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", + "dev": true, + "dependencies": { + "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git", + "ethereumjs-util": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-abi": { + "resolved": "git+https://git@github.com/ethereumjs/ethereumjs-abi.git#1ce6a1d64235fabe2aaf827fd606def55693508f", + "dev": true, + "dependencies": { + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-account": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", + "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", + "dev": true, + "dependencies": { + "ethereumjs-util": "^5.0.0", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-block": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "^1.2.2", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-block/node_modules/ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-tx": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", + "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", + "dev": true, + "dependencies": { + "ethereum-common": "^0.0.18", + "ethereumjs-util": "^5.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz", + "integrity": "sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==", + "dev": true, + "dependencies": { + "async": "^2.1.2", + "async-eventemitter": "^0.2.2", + "ethereumjs-account": "^2.0.3", + "ethereumjs-block": "~2.2.0", + "ethereumjs-common": "^1.1.0", + "ethereumjs-util": "^6.0.0", + "fake-merkle-patricia-tree": "^1.0.1", + "functional-red-black-tree": "^1.0.1", + "merkle-patricia-tree": "^2.3.2", + "rustbn.js": "~0.2.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm/node_modules/ethereumjs-block": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", + "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm/node_modules/ethereumjs-block/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm/node_modules/ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "dev": true, + "dependencies": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-ws/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-ws/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "dev": true, + "dependencies": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/merkle-patricia-tree/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-providers-http": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.11.tgz", + "integrity": "sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA==", + "dev": true, + "optional": true, + "dependencies": { + "web3-core-helpers": "1.2.11", + "xhr2-cookies": "1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-providers-ipc": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz", + "integrity": "sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ==", + "dev": true, + "optional": true, + "dependencies": { + "oboe": "2.1.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-providers-ws": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz", + "integrity": "sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg==", + "dev": true, + "optional": true, + "dependencies": { + "eventemitter3": "4.0.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.11", + "websocket": "^1.0.31" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-shh": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.11.tgz", + "integrity": "sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg==", + "dev": true, + "optional": true, + "dependencies": { + "web3-core": "1.2.11", + "web3-core-method": "1.2.11", + "web3-core-subscriptions": "1.2.11", + "web3-net": "1.2.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-utils": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.11.tgz", + "integrity": "sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ganache-core/node_modules/web3-utils/node_modules/eth-lib": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "dev": true, + "optional": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/ganache-core/node_modules/websocket": { + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.32.tgz", + "integrity": "sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q==", + "dev": true, + "dependencies": { + "bufferutil": "^4.0.1", + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/ganache-core/node_modules/websocket/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ganache-core/node_modules/websocket/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/ganache-core/node_modules/whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==", + "dev": true + }, + "node_modules/ganache-core/node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/ganache-core/node_modules/ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "optional": true, + "dependencies": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, + "node_modules/ganache-core/node_modules/ws/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "optional": true + }, + "node_modules/ganache-core/node_modules/xhr": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", + "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "dev": true, + "dependencies": { + "global": "~4.3.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/ganache-core/node_modules/xhr-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", + "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "dev": true, + "optional": true, + "dependencies": { + "buffer-to-arraybuffer": "^0.0.5", + "object-assign": "^4.1.1", + "query-string": "^5.0.1", + "simple-get": "^2.7.0", + "timed-out": "^4.0.1", + "url-set-query": "^1.0.0", + "xhr": "^2.0.4" + } + }, + "node_modules/ganache-core/node_modules/xhr-request-promise": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz", + "integrity": "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==", + "dev": true, + "optional": true, + "dependencies": { + "xhr-request": "^1.1.0" + } + }, + "node_modules/ganache-core/node_modules/xhr2-cookies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", + "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", + "dev": true, + "optional": true, + "dependencies": { + "cookiejar": "^2.1.1" + } + }, + "node_modules/ganache-core/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ganache-core/node_modules/yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", + "dev": true, + "engines": { + "node": ">=0.10.32" + } + }, + "node_modules/ganache-core/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", + "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "node_modules/get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "dev": true, + "dependencies": { + "npm-conf": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/ghost-testrpc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", + "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "node-emoji": "^1.10.0" + }, + "bin": { + "testrpc-sc": "index.js" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "dev": true, + "dependencies": { + "min-document": "^2.19.0", + "process": "~0.5.1" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/globby": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hardhat": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.0.8.tgz", + "integrity": "sha512-2tDAtOfshrBzP103dx7PQrhTwv2sqjhQStZAPwkkQTic25o2EH6HYE2++LuOG98YwqSjr0WvhvdBvKl3dCSkYA==", + "dev": true, + "dependencies": { + "@nomiclabs/ethereumjs-vm": "^4.1.1", + "@sentry/node": "^5.18.1", + "@solidity-parser/parser": "^0.11.0", + "@types/bn.js": "^4.11.5", + "@types/lru-cache": "^5.1.0", + "abort-controller": "^3.0.0", + "adm-zip": "^0.4.16", + "ansi-escapes": "^4.3.0", + "chalk": "^2.4.2", + "chokidar": "^3.4.0", + "ci-info": "^2.0.0", + "debug": "^4.1.1", + "enquirer": "^2.3.0", + "env-paths": "^2.2.0", + "eth-sig-util": "^2.5.2", + "ethereum-cryptography": "^0.1.2", + "ethereumjs-abi": "^0.6.8", + "ethereumjs-account": "^3.0.0", + "ethereumjs-block": "^2.2.0", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^6.1.0", + "find-up": "^2.1.0", + "fp-ts": "1.19.3", + "fs-extra": "^7.0.1", + "glob": "^7.1.3", + "immutable": "^4.0.0-rc.12", + "io-ts": "1.10.4", + "lodash": "^4.17.11", + "merkle-patricia-tree": "^3.0.0", + "mocha": "^7.1.2", + "node-fetch": "^2.6.0", + "qs": "^6.7.0", + "raw-body": "^2.4.1", + "resolve": "1.17.0", + "semver": "^6.3.0", + "slash": "^3.0.0", + "solc": "0.7.3", + "source-map-support": "^0.5.13", + "stacktrace-parser": "^0.1.10", + "true-case-path": "^2.2.1", + "tsort": "0.0.1", + "uuid": "^3.3.2", + "ws": "^7.2.1" + }, + "bin": { + "hardhat": "internal/cli/cli.js" + }, + "engines": { + "node": ">=8.2.0" + } + }, + "node_modules/hardhat-gas-reporter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.1.tgz", + "integrity": "sha512-YC+SCYIkBdRtISNbisU2BwDSelUdCrIKRsJXt3M9Jw1VF5CmtSZb8VuuOc2Zl4AMcEV2jEy6ZuAksYomPiApYQ==", + "dev": true, + "dependencies": { + "eth-gas-reporter": "^0.2.19" + } + }, + "node_modules/hardhat-typechain": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/hardhat-typechain/-/hardhat-typechain-0.3.3.tgz", + "integrity": "sha512-NrqP7Zng28prV3YT0lXoo1pXtZxoNCMfiZIWkf1HXjjID42JLLfSOTsvlb0okDMpz4tJaEEkgADJO69sKZxw+Q==", + "dev": true + }, + "node_modules/hardhat/node_modules/@solidity-parser/parser": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.11.1.tgz", + "integrity": "sha512-H8BSBoKE8EubJa0ONqecA2TviT3TnHeC4NpgnAHSUiuhZoQBfPB4L2P9bs8R6AoTW10Endvh3vc+fomVMIDIYQ==", + "dev": true + }, + "node_modules/hardhat/node_modules/commander": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "dev": true + }, + "node_modules/hardhat/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/hardhat/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/hardhat/node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + } + }, + "node_modules/hardhat/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/hardhat/node_modules/solc": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", + "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", + "dev": true, + "dependencies": { + "command-exists": "^1.2.8", + "commander": "3.0.2", + "follow-redirects": "^1.12.1", + "fs-extra": "^0.30.0", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "require-from-string": "^2.0.0", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solcjs" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/hardhat/node_modules/solc/node_modules/fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/hardhat/node_modules/solc/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/hardhat/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dev": true, + "dependencies": { + "has-symbol-support-x": "^1.4.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/has-values/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "node_modules/http-basic": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", + "integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==", + "dev": true, + "dependencies": { + "caseless": "^0.12.0", + "concat-stream": "^1.6.2", + "http-response-object": "^3.0.1", + "parse-cache-control": "^1.0.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "node_modules/http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", + "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=", + "dev": true + }, + "node_modules/http-response-object": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", + "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", + "dev": true, + "dependencies": { + "@types/node": "^10.0.3" + } + }, + "node_modules/http-response-object/node_modules/@types/node": { + "version": "10.17.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", + "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "dev": true + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/husky": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz", + "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "compare-versions": "^3.6.0", + "cosmiconfig": "^7.0.0", + "find-versions": "^3.2.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "slash": "^3.0.0", + "which-pm-runs": "^1.0.0" + }, + "bin": { + "husky-run": "bin/run.js", + "husky-upgrade": "lib/upgrader/bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/husky/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/husky/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/husky/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/husky/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/husky/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/husky/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/idna-uts46-hx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", + "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", + "dev": true, + "dependencies": { + "punycode": "2.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", + "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", + "dev": true + }, + "node_modules/immutable": { + "version": "4.0.0-rc.12", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz", + "integrity": "sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", + "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "dev": true, + "dependencies": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/io-ts": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", + "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", + "dev": true, + "dependencies": { + "fp-ts": "^1.0.0" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz", + "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "dev": true + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", + "dev": true, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/is-installed-globally": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.2.0.tgz", + "integrity": "sha512-g3TzWCnR/eO4Q3abCwgFjOFw7uVOfxG4m8hMr/39Jcf2YvE5mHrFKqpyuraWV4zwx9XhjnVO4nY0ZI4llzl0Pg==", + "dev": true, + "dependencies": { + "global-dirs": "^0.1.1", + "is-path-inside": "^2.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", + "dev": true + }, + "node_modules/is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, + "node_modules/is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "node_modules/isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true, + "dependencies": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/jest-docblock": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz", + "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==", + "dev": true + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonschema": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz", + "integrity": "sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/keccak": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", + "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", + "dev": true + }, + "node_modules/level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + } + }, + "node_modules/level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + } + }, + "node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/level-iterator-stream/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/level-iterator-stream/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/level-mem": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-3.0.1.tgz", + "integrity": "sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg==", + "dev": true, + "dependencies": { + "level-packager": "~4.0.0", + "memdown": "~3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-mem/node_modules/abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-mem/node_modules/immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", + "dev": true + }, + "node_modules/level-mem/node_modules/memdown": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz", + "integrity": "sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~5.0.0", + "functional-red-black-tree": "~1.0.1", + "immediate": "~3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-mem/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/level-mem/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/level-packager": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-4.0.1.tgz", + "integrity": "sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q==", + "dev": true, + "dependencies": { + "encoding-down": "~5.0.0", + "levelup": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager/node_modules/abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager/node_modules/deferred-leveldown": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", + "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", + "dev": true, + "dependencies": { + "abstract-leveldown": "~5.0.0", + "inherits": "^2.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/level-packager/node_modules/level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "dev": true, + "dependencies": { + "errno": "~0.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager/node_modules/level-iterator-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", + "integrity": "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager/node_modules/levelup": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz", + "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~4.0.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~3.0.0", + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/level-packager/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/level-packager/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/level-packager/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + } + }, + "node_modules/level-ws/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/level-ws/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "dev": true, + "dependencies": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "node_modules/levelup/node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/levelup/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "node_modules/lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true + }, + "node_modules/lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lowdb": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz", + "integrity": "sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.3", + "is-promise": "^2.1.0", + "lodash": "4", + "pify": "^3.0.0", + "steno": "^0.4.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru_map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", + "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=", + "dev": true + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-table": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", + "dev": true + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "dev": true, + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "dev": true, + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/memdown/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/memdown/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/merkle-patricia-tree": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz", + "integrity": "sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ==", + "dev": true, + "dependencies": { + "async": "^2.6.1", + "ethereumjs-util": "^5.2.0", + "level-mem": "^3.0.1", + "level-ws": "^1.0.0", + "readable-stream": "^3.0.6", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + } + }, + "node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/merkle-patricia-tree/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/merkle-patricia-tree/node_modules/level-ws": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-1.0.0.tgz", + "integrity": "sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.2.8", + "xtend": "^4.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/merkle-patricia-tree/node_modules/level-ws/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/merkle-patricia-tree/node_modules/level-ws/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/merkle-patricia-tree/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/merkle-patricia-tree/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/merkle-patricia-tree/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/micromatch/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "dependencies": { + "mime-db": "1.44.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "dev": true, + "dependencies": { + "dom-walk": "^0.1.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-promise": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", + "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", + "dev": true, + "dependencies": { + "mkdirp": "*" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mocha": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", + "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", + "dev": true, + "dependencies": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.5", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 8.10.0" + } + }, + "node_modules/mocha/node_modules/ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.1.1" + } + }, + "node_modules/mocha/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/mocha/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/mocha/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mocha/node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mocha/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mock-fs": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.13.0.tgz", + "integrity": "sha512-DD0vOdofJdoaRNtnWcrXe6RQbpHkPPmtqGq14uRX0F8ZKJ5nv89CVTYl/BZdppDxBDaV0hl75htg3abpEWlPZA==", + "dev": true + }, + "node_modules/mri": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", + "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "dependencies": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true + }, + "node_modules/nano-json-stream-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", + "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=", + "dev": true + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "dev": true + }, + "node_modules/node-emoji": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", + "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==", + "dev": true, + "dependencies": { + "lodash.toarray": "^4.4.0" + } + }, + "node_modules/node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "dependencies": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node_modules/node-environment-flags/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-gyp-build": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/nofilter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-1.0.4.tgz", + "integrity": "sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/normalize-url/node_modules/sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true, + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "dev": true, + "dependencies": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz", + "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", + "dev": true, + "dependencies": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/number-to-bn/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/oboe": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.4.tgz", + "integrity": "sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY=", + "dev": true, + "dependencies": { + "http-https": "^1.0.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true, + "bin": { + "opencollective-postinstall": "index.js" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-event": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", + "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", + "dev": true, + "dependencies": { + "p-timeout": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "dev": true, + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-cache-control": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", + "integrity": "sha1-juqz5U+laSD+Fro493+iGqzC104=", + "dev": true + }, + "node_modules/parse-code-context": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-code-context/-/parse-code-context-1.0.0.tgz", + "integrity": "sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-headers": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", + "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==", + "dev": true + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/patch-package": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.2.2.tgz", + "integrity": "sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg==", + "dev": true, + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "find-yarn-workspace-root": "^1.2.1", + "fs-extra": "^7.0.1", + "is-ci": "^2.0.0", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.0", + "rimraf": "^2.6.3", + "semver": "^5.6.0", + "slash": "^2.0.0", + "tmp": "^0.0.33" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/patch-package/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/patch-package/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/patch-package/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-type/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "dependencies": { + "semver-compare": "^1.0.0" + } + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postinstall-postinstall": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz", + "integrity": "sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ==", + "dev": true, + "hasInstallScript": true + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", + "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/prettier-plugin-solidity": { + "version": "1.0.0-alpha.60", + "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-alpha.60.tgz", + "integrity": "sha512-Dd6T0dVfw0kJrlEnLDFFE3mKRSP7zpT6zcIWvnSW+z4NBl+gmwJ7UJRZHD0CNDD6N48c+zb28xs3oF0ylDaYyg==", + "dev": true, + "dependencies": { + "@solidity-parser/parser": "^0.9.0", + "dir-to-object": "^2.0.0", + "emoji-regex": "^9.0.0", + "escape-string-regexp": "^4.0.0", + "extract-comments": "^1.1.0", + "prettier": "^2.0.5", + "semver": "^7.3.2", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/@solidity-parser/parser": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.9.0.tgz", + "integrity": "sha512-u1WzZgzOBFsGAcUhyj8DN/kop1SvrsaRT2ZVvDpVYnFI86YwbLrXCTGxefJzYGnA5Vajbbhi4aRtlxxFh69dfA==", + "dev": true, + "dependencies": { + "antlr4": "^4.8.0" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/emoji-regex": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.0.tgz", + "integrity": "sha512-DNc3KFPK18bPdElMJnf/Pkv5TXhxFU3YFDEuGLDRtPmV4rkmCjBkCSEp22u6rBHdSN9Vlp/GK7k98prmE1Jgug==", + "dev": true + }, + "node_modules/prettier-plugin-solidity/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/prettier-plugin-solidity/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-2.0.2.tgz", + "integrity": "sha512-aLb6vtOTEfJDwi1w+MBTeE20GwPVUYyn6IqNg6TtGpiOB1W3y6vKcsGFjqGeaaEtQgMLSPXTWONqh33UBuwG8A==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "execa": "^2.1.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.4", + "multimatch": "^4.0.0" + }, + "bin": { + "pretty-quick": "bin/pretty-quick.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pretty-quick/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pretty-quick/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/promise": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", + "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", + "dev": true, + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, + "node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", + "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "dependencies": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomhex": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", + "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=", + "dev": true + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", + "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.3", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", + "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "dev": true, + "dependencies": { + "minimatch": "3.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/req-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", + "integrity": "sha1-1AgrTURZgDZkD7c93qAe1T20nrw=", + "dev": true, + "dependencies": { + "req-from": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/req-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/req-from/-/req-from-2.0.0.tgz", + "integrity": "sha1-10GI5H+TeW9Kpx327jWuaJ8+DnA=", + "dev": true, + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request-promise-core": { + "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, + "dependencies": { + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/request-promise-native": { + "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, + "dependencies": { + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + }, + "node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rlp": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", + "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.1" + }, + "bin": { + "rlp": "bin/rlp" + } + }, + "node_modules/run-parallel": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", + "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", + "dev": true + }, + "node_modules/rustbn.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", + "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sc-istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.5.tgz", + "integrity": "sha512-7wR5EZFLsC4w0wSm9BUuCgW+OGKAU7PNlW5L0qwVPbh+Q1sfVn2fyzfMXYCm6rkNA5ipaCOt94nApcguQwF5Gg==", + "dev": true, + "dependencies": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "istanbul": "lib/cli.js" + } + }, + "node_modules/sc-istanbul/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/sc-istanbul/node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sc-istanbul/node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/sc-istanbul/node_modules/has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sc-istanbul/node_modules/resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "node_modules/sc-istanbul/node_modules/supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "dev": true + }, + "node_modules/scrypt-shim": { + "resolved": "git+ssh://git@github.com/web3-js/scrypt-shim.git#aafdadda13e660e25e1c525d1f5b2443f5eb1ebb", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "scryptsy": "^2.1.0", + "semver": "^6.3.0" + } + }, + "node_modules/scryptsy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz", + "integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==", + "dev": true + }, + "node_modules/secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "dev": true, + "dependencies": { + "commander": "^2.8.1" + }, + "bin": { + "seek-bunzip": "bin/seek-bunzip", + "seek-table": "bin/seek-bzip-table" + } + }, + "node_modules/semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "node_modules/semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/servify": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", + "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "dev": true, + "dependencies": { + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "request": "^2.79.0", + "xhr": "^2.3.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/sha1": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", + "integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=", + "dev": true, + "dependencies": { + "charenc": ">= 0.0.1", + "crypt": ">= 0.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shelljs": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "dev": true, + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true + }, + "node_modules/simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "dev": true, + "dependencies": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/solc": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.6.8.tgz", + "integrity": "sha512-7URBAisWVjO7dwWNpEkQ5dpRSpSF4Wm0aD5EB82D5BQKh+q7jhOxhgkG4K5gax/geM0kPZUAxnaLcgl2ZXBgMQ==", + "dev": true, + "dependencies": { + "command-exists": "^1.2.8", + "commander": "3.0.2", + "fs-extra": "^0.30.0", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "require-from-string": "^2.0.0", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solcjs" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/solc/node_modules/commander": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "dev": true + }, + "node_modules/solc/node_modules/fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/solc/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/solc/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/solc/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/solc/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/solidity-coverage": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.10.tgz", + "integrity": "sha512-F98rYoD3bscB9qIJJrqkk+o93GbOWTT54VgfO97PrcWAenOFIC1EI5DzGJSrMvmFFfr8fsMPR89on6JR0Xf/Ig==", + "dev": true, + "dependencies": { + "@solidity-parser/parser": "^0.7.0", + "@truffle/provider": "^0.1.17", + "chalk": "^2.4.2", + "death": "^1.1.0", + "detect-port": "^1.3.0", + "fs-extra": "^8.1.0", + "ganache-cli": "6.9.0", + "ghost-testrpc": "^0.0.2", + "global-modules": "^2.0.0", + "globby": "^10.0.1", + "jsonschema": "^1.2.4", + "lodash": "^4.17.15", + "node-emoji": "^1.10.0", + "pify": "^4.0.1", + "recursive-readdir": "^2.2.2", + "sc-istanbul": "^0.4.5", + "shelljs": "^0.8.3", + "web3": "1.2.6" + }, + "bin": { + "solidity-coverage": "plugins/bin.js" + } + }, + "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.7.1.tgz", + "integrity": "sha512-5ma2uuwPAEX1TPl2rAPAAuGlBkKnn2oUKQvnhTFlDIB8U/KDWX77FpHtL6Rcz+OwqSCWx9IClxACgyIEJ/GhIw==", + "dev": true + }, + "node_modules/solidity-coverage/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/solidity-coverage/node_modules/globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/solidity-coverage/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", + "dev": true, + "dependencies": { + "sort-keys": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "dev": true + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/stacktrace-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", + "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "dev": true, + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stacktrace-parser/node_modules/type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/steno": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", + "integrity": "sha1-BxEFvfwobmYVwEA8J+nXtdy4Vcs=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.3" + } + }, + "node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", + "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "node_modules/string.prototype.trimend/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.trimend/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", + "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "node_modules/string.prototype.trimstart/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.trimstart/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "dev": true, + "dependencies": { + "is-natural-number": "^4.0.1" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "dev": true, + "dependencies": { + "is-hex-prefixed": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/swarm-js": { + "version": "0.1.39", + "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.39.tgz", + "integrity": "sha512-QLMqL2rzF6n5s50BptyD6Oi0R1aWlJC5Y17SRIVXRj6OR1DRIPM7nepvrxxkjA1zNzFz6mUOMjfeqeDaWB7OOg==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.0", + "buffer": "^5.0.5", + "decompress": "^4.0.0", + "eth-lib": "^0.1.26", + "fs-extra": "^4.0.2", + "got": "^7.1.0", + "mime-types": "^2.1.16", + "mkdirp-promise": "^5.0.1", + "mock-fs": "^4.1.0", + "setimmediate": "^1.0.5", + "tar": "^4.0.2", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/swarm-js/node_modules/eth-lib": { + "version": "0.1.29", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz", + "integrity": "sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "nano-json-stream-parser": "^0.1.2", + "servify": "^0.1.12", + "ws": "^3.0.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/swarm-js/node_modules/fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/swarm-js/node_modules/got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "dev": true, + "dependencies": { + "decompress-response": "^3.2.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-plain-obj": "^1.1.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "p-cancelable": "^0.3.0", + "p-timeout": "^1.1.1", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "url-parse-lax": "^1.0.0", + "url-to-options": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/swarm-js/node_modules/p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/swarm-js/node_modules/p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "dev": true, + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/swarm-js/node_modules/prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/swarm-js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/swarm-js/node_modules/url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "dependencies": { + "prepend-http": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/swarm-js/node_modules/ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, + "node_modules/sync-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", + "integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==", + "dev": true, + "dependencies": { + "http-response-object": "^3.0.1", + "sync-rpc": "^1.2.1", + "then-request": "^6.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/sync-rpc": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz", + "integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==", + "dev": true, + "dependencies": { + "get-port": "^3.1.0" + } + }, + "node_modules/tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dev": true, + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/tar-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/tar-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/tar-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/tar-stream/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/temp-hardhat-etherscan": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/temp-hardhat-etherscan/-/temp-hardhat-etherscan-2.0.2.tgz", + "integrity": "sha512-q9+OMPXlsXZ+2fnF+Xmvv0J9vNJChwOXVGJIATiDJr7Qe8LzTwgs55C4l4NKMWPLe4PE9UjcQMVntRfXGTF9vA==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.0.2", + "@ethersproject/address": "^5.0.2", + "cbor": "^5.0.2", + "fs-extra": "^7.0.1", + "lodash": "^4.17.11", + "node-fetch": "^2.6.0", + "semver": "^6.3.0" + } + }, + "node_modules/test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", + "dev": true, + "dependencies": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/test-value/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/testrpc": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/testrpc/-/testrpc-0.0.1.tgz", + "integrity": "sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA==", + "dev": true + }, + "node_modules/then-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", + "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", + "dev": true, + "dependencies": { + "@types/concat-stream": "^1.6.0", + "@types/form-data": "0.0.33", + "@types/node": "^8.0.0", + "@types/qs": "^6.2.31", + "caseless": "~0.12.0", + "concat-stream": "^1.6.0", + "form-data": "^2.2.0", + "http-basic": "^8.1.1", + "http-response-object": "^3.0.1", + "promise": "^8.0.0", + "qs": "^6.4.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/then-request/node_modules/@types/node": { + "version": "8.10.66", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", + "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.2.tgz", + "integrity": "sha512-OyCLAKU1HzBjL6Ev3gxUeraJNlbNingmi8IrHHEsYH8LTmEuhvYfqvhn2F/je+mjf4N58UmZ96OMEy1JanSCpA==", + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "dev": true + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tough-cookie/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/true-case-path": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-2.2.1.tgz", + "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==", + "dev": true + }, + "node_modules/ts-essentials": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-2.0.12.tgz", + "integrity": "sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w==", + "dev": true + }, + "node_modules/ts-generator": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ts-generator/-/ts-generator-0.1.1.tgz", + "integrity": "sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ==", + "dev": true, + "dependencies": { + "@types/mkdirp": "^0.5.2", + "@types/prettier": "^2.1.1", + "@types/resolve": "^0.0.8", + "chalk": "^2.4.1", + "glob": "^7.1.2", + "mkdirp": "^0.5.1", + "prettier": "^2.1.2", + "resolve": "^1.8.1", + "ts-essentials": "^1.0.0" + }, + "bin": { + "ts-generator": "dist/cli/run.js" + } + }, + "node_modules/ts-generator/node_modules/ts-essentials": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-1.0.4.tgz", + "integrity": "sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ==", + "dev": true + }, + "node_modules/ts-node": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", + "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", + "dev": true, + "dependencies": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + } + }, + "node_modules/tslint-config-prettier": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", + "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", + "dev": true, + "bin": { + "tslint-config-prettier-check": "bin/check.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/tslint-plugin-prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslint-plugin-prettier/-/tslint-plugin-prettier-2.3.0.tgz", + "integrity": "sha512-F9e4K03yc9xuvv+A0v1EmjcnDwpz8SpCD8HzqSDe0eyg34cBinwn9JjmnnRrNAs4HdleRQj7qijp+P/JTxt4vA==", + "dev": true, + "dependencies": { + "eslint-plugin-prettier": "^2.2.0", + "lines-and-columns": "^1.1.6", + "tslib": "^1.7.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/tslint/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tslint/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/tsort": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", + "integrity": "sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=", + "dev": true + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "dev": true + }, + "node_modules/tweetnacl-util": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", + "dev": true + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typechain": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-4.0.0.tgz", + "integrity": "sha512-XQUojf02bXyxXNGI0WeCphnh++5eWr9wYH8jm0XqHNv8yENpFrRyX8ffVlkhCnDOOB/jEJJVQytLAOU+Qn0N9Q==", + "dev": true, + "dependencies": { + "command-line-args": "^4.0.7", + "debug": "^4.1.1", + "fs-extra": "^7.0.0", + "js-sha3": "^0.8.0", + "lodash": "^4.17.15", + "ts-essentials": "^6.0.3", + "ts-generator": "^0.1.1" + }, + "bin": { + "typechain": "dist/cli/cli.js" + } + }, + "node_modules/typechain/node_modules/ts-essentials": { + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-6.0.7.tgz", + "integrity": "sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw==", + "dev": true + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", + "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.6.tgz", + "integrity": "sha512-oASI1FOJ7BBFkSCNDZ446EgkSuHkOZBuqRFrwXIKWCoXw8ZXQETooTQjkAcBS03Acab7ubCKsXnwuV2svy061g==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/url-set-query": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", + "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=", + "dev": true + }, + "node_modules/url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/web3": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.6.tgz", + "integrity": "sha512-tpu9fLIComgxGrFsD8LUtA4s4aCZk7px8UfcdEy6kS2uDi/ZfR07KJqpXZMij7Jvlq+cQrTAhsPSiBVvoMaivA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@types/node": "^12.6.1", + "web3-bzz": "1.2.6", + "web3-core": "1.2.6", + "web3-eth": "1.2.6", + "web3-eth-personal": "1.2.6", + "web3-net": "1.2.6", + "web3-shh": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-bzz": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.2.tgz", + "integrity": "sha512-b1O2ObsqUN1lJxmFSjvnEC4TsaCbmh7Owj3IAIWTKqL9qhVgx7Qsu5O9cD13pBiSPNZJ68uJPaKq380QB4NWeA==", + "dev": true, + "dependencies": { + "@types/node": "^10.12.18", + "got": "9.6.0", + "swarm-js": "0.1.39", + "underscore": "1.9.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-bzz/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3-bzz/node_modules/@types/node": { + "version": "10.17.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", + "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "dev": true + }, + "node_modules/web3-bzz/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3-bzz/node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3-bzz/node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3-bzz/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3-bzz/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/web3-bzz/node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/web3-bzz/node_modules/normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3-bzz/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3-core": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.2.tgz", + "integrity": "sha512-miHAX3qUgxV+KYfaOY93Hlc3kLW2j5fH8FJy6kSxAv+d4d5aH0wwrU2IIoJylQdT+FeenQ38sgsCnFu9iZ1hCQ==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.4", + "@types/node": "^12.6.1", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-requestmanager": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-helpers": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.2.tgz", + "integrity": "sha512-HJrRsIGgZa1jGUIhvGz4S5Yh6wtOIo/TMIsSLe+Xay+KVnbseJpPprDI5W3s7H2ODhMQTbogmmUFquZweW2ImQ==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-eth-iban": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-helpers/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-core-helpers/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-core-helpers/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-method": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.2.tgz", + "integrity": "sha512-szR4fDSBxNHaF1DFqE+j6sFR/afv9Aa36OW93saHZnrh+iXSrYeUUDfugeNcRlugEKeUCkd4CZylfgbK2SKYJA==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2", + "web3-core-promievent": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-method/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-core-method/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-core-method/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-promievent": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.2.tgz", + "integrity": "sha512-tKvYeT8bkUfKABcQswK6/X79blKTKYGk949urZKcLvLDEaWrM3uuzDwdQT3BNKzQ3vIvTggFPX9BwYh0F1WwqQ==", + "dev": true, + "dependencies": { + "any-promise": "1.3.0", + "eventemitter3": "3.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-requestmanager": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.2.tgz", + "integrity": "sha512-a+gSbiBRHtHvkp78U2bsntMGYGF2eCb6219aMufuZWeAZGXJ63Wc2321PCbA8hF9cQrZI4EoZ4kVLRI4OF15Hw==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2", + "web3-providers-http": "1.2.2", + "web3-providers-ipc": "1.2.2", + "web3-providers-ws": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-subscriptions": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.2.tgz", + "integrity": "sha512-QbTgigNuT4eicAWWr7ahVpJyM8GbICsR1Ys9mJqzBEwpqS+RXTRVSkwZ2IsxO+iqv6liMNwGregbJLq4urMFcQ==", + "dev": true, + "dependencies": { + "eventemitter3": "3.1.2", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core/node_modules/@types/node": { + "version": "12.19.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", + "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", + "dev": true + }, + "node_modules/web3-core/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-core/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-core/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.2.tgz", + "integrity": "sha512-UXpC74mBQvZzd4b+baD4Ocp7g+BlwxhBHumy9seyE/LMIcMlePXwCKzxve9yReNpjaU16Mmyya6ZYlyiKKV8UA==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-eth-abi": "1.2.2", + "web3-eth-accounts": "1.2.2", + "web3-eth-contract": "1.2.2", + "web3-eth-ens": "1.2.2", + "web3-eth-iban": "1.2.2", + "web3-eth-personal": "1.2.2", + "web3-net": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-abi": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.2.tgz", + "integrity": "sha512-Yn/ZMgoOLxhTVxIYtPJ0eS6pnAnkTAaJgUJh1JhZS4ekzgswMfEYXOwpMaD5eiqPJLpuxmZFnXnBZlnQ1JMXsw==", + "dev": true, + "dependencies": { + "ethers": "4.0.0-beta.3", + "underscore": "1.9.1", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-abi/node_modules/@types/node": { + "version": "10.17.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", + "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "dev": true + }, + "node_modules/web3-eth-abi/node_modules/elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "dev": true, + "dependencies": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/web3-eth-abi/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-abi/node_modules/eth-lib/node_modules/elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/web3-eth-abi/node_modules/ethers": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", + "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", + "dev": true, + "dependencies": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.3", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/web3-eth-abi/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web3-eth-abi/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/web3-eth-abi/node_modules/scrypt-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", + "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", + "dev": true + }, + "node_modules/web3-eth-abi/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", + "dev": true + }, + "node_modules/web3-eth-abi/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", + "dev": true + }, + "node_modules/web3-eth-abi/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-abi/node_modules/web3-utils/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth-accounts": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.2.tgz", + "integrity": "sha512-KzHOEyXOEZ13ZOkWN3skZKqSo5f4Z1ogPFNn9uZbKCz+kSp+gCAEKxyfbOsB/JMAp5h7o7pb6eYsPCUBJmFFiA==", + "dev": true, + "dependencies": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "ethereumjs-common": "^1.3.2", + "ethereumjs-tx": "^2.1.1", + "scrypt-shim": "github:web3-js/scrypt-shim", + "underscore": "1.9.1", + "uuid": "3.3.2", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-accounts/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-accounts/node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/web3-eth-accounts/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-accounts/node_modules/web3-utils/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth-contract": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.2.tgz", + "integrity": "sha512-EKT2yVFws3FEdotDQoNsXTYL798+ogJqR2//CaGwx3p0/RvQIgfzEwp8nbgA6dMxCsn9KOQi7OtklzpnJMkjtA==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.4", + "underscore": "1.9.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-promievent": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-eth-abi": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-contract/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth-contract/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-contract/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-ens": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.2.tgz", + "integrity": "sha512-CFjkr2HnuyMoMFBoNUWojyguD4Ef+NkyovcnUc/iAb9GP4LHohKrODG4pl76R5u61TkJGobC2ij6TyibtsyVYg==", + "dev": true, + "dependencies": { + "eth-ens-namehash": "2.0.8", + "underscore": "1.9.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-promievent": "1.2.2", + "web3-eth-abi": "1.2.2", + "web3-eth-contract": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-ens/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth-ens/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-ens/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-iban": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.2.tgz", + "integrity": "sha512-gxKXBoUhaTFHr0vJB/5sd4i8ejF/7gIsbM/VvemHT3tF5smnmY6hcwSMmn7sl5Gs+83XVb/BngnnGkf+I/rsrQ==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-iban/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth-iban/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-iban/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-personal": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.2.tgz", + "integrity": "sha512-4w+GLvTlFqW3+q4xDUXvCEMU7kRZ+xm/iJC8gm1Li1nXxwwFbs+Y+KBK6ZYtoN1qqAnHR+plYpIoVo27ixI5Rg==", + "dev": true, + "dependencies": { + "@types/node": "^12.6.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-net": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-personal/node_modules/@types/node": { + "version": "12.19.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", + "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", + "dev": true + }, + "node_modules/web3-eth-personal/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth-personal/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-personal/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-eth/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-net": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.2.tgz", + "integrity": "sha512-K07j2DXq0x4UOJgae65rWZKraOznhk8v5EGSTdFqASTx7vWE/m+NqBijBYGEsQY1lSMlVaAY9UEQlcXK5HzXTw==", + "dev": true, + "dependencies": { + "web3-core": "1.2.2", + "web3-core-method": "1.2.2", + "web3-utils": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-net/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3-net/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-net/node_modules/web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-http": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.2.tgz", + "integrity": "sha512-BNZ7Hguy3eBszsarH5gqr9SIZNvqk9eKwqwmGH1LQS1FL3NdoOn7tgPPdddrXec4fL94CwgNk4rCU+OjjZRNDg==", + "dev": true, + "dependencies": { + "web3-core-helpers": "1.2.2", + "xhr2-cookies": "1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-ipc": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.2.tgz", + "integrity": "sha512-t97w3zi5Kn/LEWGA6D9qxoO0LBOG+lK2FjlEdCwDQatffB/+vYrzZ/CLYVQSoyFZAlsDoBasVoYSWZK1n39aHA==", + "dev": true, + "dependencies": { + "oboe": "2.1.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-ws": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.2.tgz", + "integrity": "sha512-Wb1mrWTGMTXOpJkL0yGvL/WYLt8fUIXx8k/l52QB2IiKzvyd42dTWn4+j8IKXGSYYzOm7NMqv6nhA5VDk12VfA==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2", + "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-shh": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.2.tgz", + "integrity": "sha512-og258NPhlBn8yYrDWjoWBBb6zo1OlBgoWGT+LL5/LPqRbjPe09hlOYHgscAAr9zZGtohTOty7RrxYw6Z6oDWCg==", + "dev": true, + "dependencies": { + "web3-core": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-net": "1.2.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.0.tgz", + "integrity": "sha512-2mS5axFCbkhicmoDRuJeuo0TVGQDgC2sPi/5dblfVC+PMtX0efrb8Xlttv/eGkq7X4E83Pds34FH98TP2WOUZA==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3/node_modules/@types/node": { + "version": "12.19.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", + "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", + "dev": true + }, + "node_modules/web3/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/web3/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3/node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3/node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3/node_modules/eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3/node_modules/ethers": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", + "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", + "dev": true, + "dependencies": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.3", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/web3/node_modules/ethers/node_modules/@types/node": { + "version": "10.17.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", + "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "dev": true + }, + "node_modules/web3/node_modules/ethers/node_modules/elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "dev": true, + "dependencies": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/web3/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/web3/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web3/node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/web3/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "node_modules/web3/node_modules/normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3/node_modules/scrypt-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", + "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", + "dev": true + }, + "node_modules/web3/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", + "dev": true + }, + "node_modules/web3/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", + "dev": true + }, + "node_modules/web3/node_modules/web3-bzz": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.6.tgz", + "integrity": "sha512-9NiHLlxdI1XeFtbPJAmi2jnnIHVF+GNy517wvOS72P7ZfuJTPwZaSNXfT01vWgPPE9R96/uAHDWHOg+T4WaDQQ==", + "dev": true, + "dependencies": { + "@types/node": "^10.12.18", + "got": "9.6.0", + "swarm-js": "0.1.39", + "underscore": "1.9.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-bzz/node_modules/@types/node": { + "version": "10.17.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", + "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "dev": true + }, + "node_modules/web3/node_modules/web3-core": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.6.tgz", + "integrity": "sha512-y/QNBFtr5cIR8vxebnotbjWJpOnO8LDYEAzZjeRRUJh2ijmhjoYk7dSNx9ExgC0UCfNFRoNCa9dGRu/GAxwRlw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.4", + "@types/node": "^12.6.1", + "web3-core-helpers": "1.2.6", + "web3-core-method": "1.2.6", + "web3-core-requestmanager": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-core-helpers": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.6.tgz", + "integrity": "sha512-gYKWmC2HmO7RcDzpo4L1K8EIoy5L8iubNDuTC6q69UxczwqKF/Io0kbK/1Z10Av++NlzOSiuyGp2gc4t4UOsDw==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-eth-iban": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-core-method": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.6.tgz", + "integrity": "sha512-r2dzyPEonqkBg7Mugq5dknhV5PGaZTHBZlS/C+aMxNyQs3T3eaAsCTqlQDitwNUh/sUcYPEGF0Vo7ahYK4k91g==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.6", + "web3-core-promievent": "1.2.6", + "web3-core-subscriptions": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-core-promievent": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.6.tgz", + "integrity": "sha512-km72kJef/qtQNiSjDJJVHIZvoVOm6ytW3FCYnOcCs7RIkviAb5JYlPiye0o4pJOLzCXYID7DK7Q9bhY8qWb1lw==", + "dev": true, + "dependencies": { + "any-promise": "1.3.0", + "eventemitter3": "3.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-core-requestmanager": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.6.tgz", + "integrity": "sha512-QU2cbsj9Dm0r6om40oSwk8Oqbp3wTa08tXuMpSmeOTkGZ3EMHJ1/4LiJ8shwg1AvPMrKVU0Nri6+uBNCdReZ+g==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.6", + "web3-providers-http": "1.2.6", + "web3-providers-ipc": "1.2.6", + "web3-providers-ws": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-core-subscriptions": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.6.tgz", + "integrity": "sha512-M0PzRrP2Ct13x3wPulFtc5kENH4UtnPxO9YxkfQlX2WRKENWjt4Rfq+BCVGYEk3rTutDfWrjfzjmqMRvXqEY5Q==", + "dev": true, + "dependencies": { + "eventemitter3": "3.1.2", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.6.tgz", + "integrity": "sha512-ROWlDPzh4QX6tlGGGlAK6X4kA2n0/cNj/4kb0nNVWkRouGmYO0R8k6s47YxYHvGiXt0s0++FUUv5vAbWovtUQw==", + "dev": true, + "dependencies": { + "underscore": "1.9.1", + "web3-core": "1.2.6", + "web3-core-helpers": "1.2.6", + "web3-core-method": "1.2.6", + "web3-core-subscriptions": "1.2.6", + "web3-eth-abi": "1.2.6", + "web3-eth-accounts": "1.2.6", + "web3-eth-contract": "1.2.6", + "web3-eth-ens": "1.2.6", + "web3-eth-iban": "1.2.6", + "web3-eth-personal": "1.2.6", + "web3-net": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth-abi": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.6.tgz", + "integrity": "sha512-w9GAyyikn8nSifSDZxAvU9fxtQSX+W2xQWMmrtTXmBGCaE4/ywKOSPAO78gq8AoU4Wq5yqVGKZLLbfpt7/sHlA==", + "dev": true, + "dependencies": { + "ethers": "4.0.0-beta.3", + "underscore": "1.9.1", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth-accounts": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.6.tgz", + "integrity": "sha512-cDVtonHRgzqi/ZHOOf8kfCQWFEipcfQNAMzXIaKZwc0UUD9mgSI5oJrN45a89Ze+E6Lz9m77cDG5Ax9zscSkcw==", + "dev": true, + "dependencies": { + "@web3-js/scrypt-shim": "^0.1.0", + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "^0.2.8", + "ethereumjs-common": "^1.3.2", + "ethereumjs-tx": "^2.1.1", + "underscore": "1.9.1", + "uuid": "3.3.2", + "web3-core": "1.2.6", + "web3-core-helpers": "1.2.6", + "web3-core-method": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth-accounts/node_modules/eth-lib": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3/node_modules/web3-eth-accounts/node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/web3/node_modules/web3-eth-contract": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.6.tgz", + "integrity": "sha512-ak4xbHIhWgsbdPCkSN+HnQc1SH4c856y7Ly+S57J/DQVzhFZemK5HvWdpwadJrQTcHET3ZeId1vq3kmW7UYodw==", + "dev": true, + "dependencies": { + "@types/bn.js": "^4.11.4", + "underscore": "1.9.1", + "web3-core": "1.2.6", + "web3-core-helpers": "1.2.6", + "web3-core-method": "1.2.6", + "web3-core-promievent": "1.2.6", + "web3-core-subscriptions": "1.2.6", + "web3-eth-abi": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth-ens": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.6.tgz", + "integrity": "sha512-8UEqt6fqR/dji/jBGPFAyBs16OJjwi0t2dPWXPyGXmty/fH+osnXwWXE4HRUyj4xuafiM5P1YkXMsPhKEadjiw==", + "dev": true, + "dependencies": { + "eth-ens-namehash": "2.0.8", + "underscore": "1.9.1", + "web3-core": "1.2.6", + "web3-core-helpers": "1.2.6", + "web3-core-promievent": "1.2.6", + "web3-eth-abi": "1.2.6", + "web3-eth-contract": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth-iban": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.6.tgz", + "integrity": "sha512-TPMc3BW9Iso7H+9w+ytbqHK9wgOmtocyCD3PaAe5Eie50KQ/j7ThA60dGJnxItVo6yyRv5pZAYxPVob9x/fJlg==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-eth-personal": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.6.tgz", + "integrity": "sha512-T2NUkh1plY8d7wePXSoHnaiKOd8dLNFaQfgBl9JHU6S7IJrG9jnYD9bVxLEgRUfHs9gKf9tQpDf7AcPFdq/A8g==", + "dev": true, + "dependencies": { + "@types/node": "^12.6.1", + "web3-core": "1.2.6", + "web3-core-helpers": "1.2.6", + "web3-core-method": "1.2.6", + "web3-net": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-net": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.6.tgz", + "integrity": "sha512-hsNHAPddrhgjWLmbESW0KxJi2GnthPcow0Sqpnf4oB6+/+ZnQHU9OsIyHb83bnC1OmunrK2vf9Ye2mLPdFIu3A==", + "dev": true, + "dependencies": { + "web3-core": "1.2.6", + "web3-core-method": "1.2.6", + "web3-utils": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-providers-http": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.6.tgz", + "integrity": "sha512-2+SaFCspb5f82QKuHB3nEPQOF9iSWxRf7c18fHtmnLNVkfG9SwLN1zh67bYn3tZGUdOI3gj8aX4Uhfpwx9Ezpw==", + "dev": true, + "dependencies": { + "web3-core-helpers": "1.2.6", + "xhr2-cookies": "1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-providers-ipc": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.6.tgz", + "integrity": "sha512-b0Es+/GTZyk5FG3SgUDW+2/mBwJAXWt5LuppODptiOas8bB2khLjG6+Gm1K4uwOb+1NJGPt5mZZ8Wi7vibtQ+A==", + "dev": true, + "dependencies": { + "oboe": "2.1.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-providers-ws": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.6.tgz", + "integrity": "sha512-20waSYX+gb5M5yKhug5FIwxBBvkKzlJH7sK6XEgdOx6BZ9YYamLmvg9wcRVtnSZO8hV/3cWenO/tRtTrHVvIgQ==", + "dev": true, + "dependencies": { + "@web3-js/websocket": "^1.0.29", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-shh": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.6.tgz", + "integrity": "sha512-rouWyOOM6YMbLQd65grpj8BBezQfgNeRRX+cGyW4xsn6Xgu+B73Zvr6OtA/ftJwwa9bqHGpnLrrLMeWyy4YLUw==", + "dev": true, + "dependencies": { + "web3-core": "1.2.6", + "web3-core-method": "1.2.6", + "web3-core-subscriptions": "1.2.6", + "web3-net": "1.2.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3/node_modules/web3-utils": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.6.tgz", + "integrity": "sha512-8/HnqG/l7dGmKMgEL9JeKPTtjScxOePTzopv5aaKFExPfaBrYRkgoMqhoowCiAl/s16QaTn4DoIF1QC4YsT7Mg==", + "dev": true, + "dependencies": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/websocket": { + "resolved": "git+ssh://git@github.com/web3-js/WebSocket-Node.git#ef5ea2f41daf4a2113b80c9223df884b4d56c400", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "nan": "^2.14.0", + "typedarray-to-buffer": "^3.1.5", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/websocket/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/websocket/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", + "dev": true, + "bin": { + "window-size": "cli.js" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", + "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==", + "dev": true, + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/xhr": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", + "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "dev": true, + "dependencies": { + "global": "~4.3.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/xhr-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", + "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "dev": true, + "dependencies": { + "buffer-to-arraybuffer": "^0.0.5", + "object-assign": "^4.1.1", + "query-string": "^5.0.1", + "simple-get": "^2.7.0", + "timed-out": "^4.0.1", + "url-set-query": "^1.0.0", + "xhr": "^2.0.4" + } + }, + "node_modules/xhr-request-promise": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz", + "integrity": "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==", + "dev": true, + "dependencies": { + "xhr-request": "^1.1.0" + } + }, + "node_modules/xhr/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/xhr2-cookies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", + "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", + "dev": true, + "dependencies": { + "cookiejar": "^2.1.1" + } + }, + "node_modules/xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "node_modules/yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", + "dev": true, + "engines": { + "node": ">=0.10.32" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "dependencies": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + } + }, "dependencies": { "@babel/code-frame": { "version": "7.10.4", @@ -5583,13 +30913,11 @@ "dependencies": { "ansi-regex": { "version": "4.1.0", - "resolved": false, "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "ansi-styles": { "version": "3.2.1", - "resolved": false, "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { @@ -5598,7 +30926,6 @@ }, "bindings": { "version": "1.5.0", - "resolved": false, "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, "requires": { @@ -5607,7 +30934,6 @@ }, "bip66": { "version": "1.1.5", - "resolved": false, "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", "dev": true, "requires": { @@ -5616,19 +30942,16 @@ }, "bn.js": { "version": "4.11.8", - "resolved": false, "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, "brorand": { "version": "1.1.0", - "resolved": false, "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, "browserify-aes": { "version": "1.2.0", - "resolved": false, "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -5642,25 +30965,21 @@ }, "buffer-from": { "version": "1.1.1", - "resolved": false, "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, "buffer-xor": { "version": "1.0.3", - "resolved": false, "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, "camelcase": { "version": "5.3.1", - "resolved": false, "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "cipher-base": { "version": "1.0.4", - "resolved": false, "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { @@ -5670,7 +30989,6 @@ }, "cliui": { "version": "5.0.0", - "resolved": false, "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { @@ -5681,7 +30999,6 @@ }, "color-convert": { "version": "1.9.3", - "resolved": false, "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { @@ -5690,13 +31007,11 @@ }, "color-name": { "version": "1.1.3", - "resolved": false, "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "create-hash": { "version": "1.2.0", - "resolved": false, "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { @@ -5709,7 +31024,6 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": false, "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { @@ -5723,7 +31037,6 @@ }, "cross-spawn": { "version": "6.0.5", - "resolved": false, "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { @@ -5736,13 +31049,11 @@ }, "decamelize": { "version": "1.2.0", - "resolved": false, "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "drbg.js": { "version": "1.0.1", - "resolved": false, "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", "dev": true, "requires": { @@ -5753,7 +31064,6 @@ }, "elliptic": { "version": "6.5.0", - "resolved": false, "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", "dev": true, "requires": { @@ -5768,13 +31078,11 @@ }, "emoji-regex": { "version": "7.0.3", - "resolved": false, "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "end-of-stream": { "version": "1.4.1", - "resolved": false, "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { @@ -5783,7 +31091,6 @@ }, "ethereumjs-util": { "version": "6.1.0", - "resolved": false, "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", "dev": true, "requires": { @@ -5798,7 +31105,6 @@ }, "ethjs-util": { "version": "0.1.6", - "resolved": false, "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", "dev": true, "requires": { @@ -5808,7 +31114,6 @@ }, "evp_bytestokey": { "version": "1.0.3", - "resolved": false, "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, "requires": { @@ -5818,7 +31123,6 @@ }, "execa": { "version": "1.0.0", - "resolved": false, "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { @@ -5833,13 +31137,11 @@ }, "file-uri-to-path": { "version": "1.0.0", - "resolved": false, "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "dev": true }, "find-up": { "version": "3.0.0", - "resolved": false, "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { @@ -5848,13 +31150,11 @@ }, "get-caller-file": { "version": "2.0.5", - "resolved": false, "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-stream": { "version": "4.1.0", - "resolved": false, "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "requires": { @@ -5863,7 +31163,6 @@ }, "hash-base": { "version": "3.0.4", - "resolved": false, "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, "requires": { @@ -5873,7 +31172,6 @@ }, "hash.js": { "version": "1.1.7", - "resolved": false, "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, "requires": { @@ -5883,7 +31181,6 @@ }, "hmac-drbg": { "version": "1.0.1", - "resolved": false, "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { @@ -5894,43 +31191,36 @@ }, "inherits": { "version": "2.0.4", - "resolved": false, "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "invert-kv": { "version": "2.0.0", - "resolved": false, "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", - "resolved": false, "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "is-hex-prefixed": { "version": "1.0.0", - "resolved": false, "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", "dev": true }, "is-stream": { "version": "1.1.0", - "resolved": false, "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, "isexe": { "version": "2.0.0", - "resolved": false, "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "keccak": { "version": "1.4.0", - "resolved": false, "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", "dev": true, "requires": { @@ -5942,7 +31232,6 @@ }, "lcid": { "version": "2.0.0", - "resolved": false, "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { @@ -5951,7 +31240,6 @@ }, "locate-path": { "version": "3.0.0", - "resolved": false, "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { @@ -5961,7 +31249,6 @@ }, "map-age-cleaner": { "version": "0.1.3", - "resolved": false, "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", "dev": true, "requires": { @@ -5970,7 +31257,6 @@ }, "md5.js": { "version": "1.3.5", - "resolved": false, "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, "requires": { @@ -5981,7 +31267,6 @@ }, "mem": { "version": "4.3.0", - "resolved": false, "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, "requires": { @@ -5992,37 +31277,31 @@ }, "mimic-fn": { "version": "2.1.0", - "resolved": false, "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "minimalistic-assert": { "version": "1.0.1", - "resolved": false, "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, "minimalistic-crypto-utils": { "version": "1.0.1", - "resolved": false, "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", "dev": true }, "nan": { "version": "2.14.0", - "resolved": false, "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "dev": true }, "nice-try": { "version": "1.0.5", - "resolved": false, "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "npm-run-path": { "version": "2.0.2", - "resolved": false, "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { @@ -6031,7 +31310,6 @@ }, "once": { "version": "1.4.0", - "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { @@ -6040,7 +31318,6 @@ }, "os-locale": { "version": "3.1.0", - "resolved": false, "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { @@ -6051,25 +31328,21 @@ }, "p-defer": { "version": "1.0.0", - "resolved": false, "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", "dev": true }, "p-finally": { "version": "1.0.0", - "resolved": false, "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, "p-is-promise": { "version": "2.1.0", - "resolved": false, "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", "dev": true }, "p-limit": { "version": "2.2.0", - "resolved": false, "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { @@ -6078,7 +31351,6 @@ }, "p-locate": { "version": "3.0.0", - "resolved": false, "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { @@ -6087,25 +31359,21 @@ }, "p-try": { "version": "2.2.0", - "resolved": false, "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "path-exists": { "version": "3.0.0", - "resolved": false, "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, "path-key": { "version": "2.0.1", - "resolved": false, "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "pump": { "version": "3.0.0", - "resolved": false, "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { @@ -6115,19 +31383,16 @@ }, "require-directory": { "version": "2.1.1", - "resolved": false, "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { "version": "2.0.0", - "resolved": false, "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "ripemd160": { "version": "2.0.2", - "resolved": false, "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { @@ -6137,7 +31402,6 @@ }, "rlp": { "version": "2.2.3", - "resolved": false, "integrity": "sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==", "dev": true, "requires": { @@ -6147,13 +31411,11 @@ }, "safe-buffer": { "version": "5.2.0", - "resolved": false, "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", "dev": true }, "secp256k1": { "version": "3.7.1", - "resolved": false, "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", "dev": true, "requires": { @@ -6169,19 +31431,16 @@ }, "semver": { "version": "5.7.0", - "resolved": false, "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "sha.js": { "version": "2.4.11", - "resolved": false, "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -6191,7 +31450,6 @@ }, "shebang-command": { "version": "1.2.0", - "resolved": false, "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { @@ -6200,25 +31458,21 @@ }, "shebang-regex": { "version": "1.0.0", - "resolved": false, "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, "source-map": { "version": "0.6.1", - "resolved": false, "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "source-map-support": { "version": "0.5.12", - "resolved": false, "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", "dev": true, "requires": { @@ -6228,7 +31482,6 @@ }, "string-width": { "version": "3.1.0", - "resolved": false, "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { @@ -6239,7 +31492,6 @@ }, "strip-ansi": { "version": "5.2.0", - "resolved": false, "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { @@ -6248,13 +31500,11 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": false, "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "strip-hex-prefix": { "version": "1.0.0", - "resolved": false, "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", "dev": true, "requires": { @@ -6263,7 +31513,6 @@ }, "which": { "version": "1.3.1", - "resolved": false, "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { @@ -6272,13 +31521,11 @@ }, "which-module": { "version": "2.0.0", - "resolved": false, "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "wrap-ansi": { "version": "5.1.0", - "resolved": false, "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { @@ -6289,19 +31536,16 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "y18n": { "version": "4.0.0", - "resolved": false, "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yargs": { "version": "13.2.4", - "resolved": false, "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", "dev": true, "requires": { @@ -6320,7 +31564,6 @@ }, "yargs-parser": { "version": "13.1.1", - "resolved": false, "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { @@ -13600,6 +38843,23 @@ "dev": true, "optional": true }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, "string.prototype.trim": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.2.tgz", @@ -13652,23 +38912,6 @@ "es-abstract": "^1.17.5" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, "strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -14609,8 +39852,8 @@ }, "ethereumjs-abi": { "version": "git+https://git@github.com/ethereumjs/ethereumjs-abi.git#1ce6a1d64235fabe2aaf827fd606def55693508f", - "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "dev": true, + "from": "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" @@ -16761,6 +42004,12 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, + "lru_map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", + "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=", + "dev": true + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -16770,12 +42019,6 @@ "yallist": "^3.0.2" } }, - "lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=", - "dev": true - }, "ltgt": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", @@ -18899,9 +44142,9 @@ "dev": true }, "scrypt-shim": { - "version": "github:web3-js/scrypt-shim#aafdadda13e660e25e1c525d1f5b2443f5eb1ebb", - "from": "github:web3-js/scrypt-shim", + "version": "git+ssh://git@github.com/web3-js/scrypt-shim.git#aafdadda13e660e25e1c525d1f5b2443f5eb1ebb", "dev": true, + "from": "scrypt-shim@github:web3-js/scrypt-shim", "requires": { "scryptsy": "^2.1.0", "semver": "^6.3.0" @@ -19605,6 +44848,15 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "dev": true }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -19691,15 +44943,6 @@ } } }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -21965,9 +47208,9 @@ } }, "websocket": { - "version": "github:web3-js/WebSocket-Node#ef5ea2f41daf4a2113b80c9223df884b4d56c400", - "from": "github:web3-js/WebSocket-Node#polyfill/globalThis", + "version": "git+ssh://git@github.com/web3-js/WebSocket-Node.git#ef5ea2f41daf4a2113b80c9223df884b4d56c400", "dev": true, + "from": "websocket@github:web3-js/WebSocket-Node#polyfill/globalThis", "requires": { "debug": "^2.2.0", "es5-ext": "^0.10.50", diff --git a/tasks/deployments/deploy-wethGateWay.ts b/tasks/deployments/deploy-wethGateWay.ts deleted file mode 100644 index 83611efc..00000000 --- a/tasks/deployments/deploy-wethGateWay.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { task } from 'hardhat/config'; - -import { deployWETHGateway } from '../../helpers/contracts-deployments'; - -const CONTRACT_NAME = 'WETHGateway'; - -task(`deploy-${CONTRACT_NAME}`, `Deploys the ${CONTRACT_NAME} contract`) - .addParam('weth', 'Address of the weth token') - .addFlag('verify', `Verify ${CONTRACT_NAME} contract via Etherscan API.`) - .setAction(async ({ weth, verify }, localBRE) => { - await localBRE.run('set-DRE'); - - if (!localBRE.network.config.chainId) { - throw new Error('INVALID_CHAIN_ID'); - } - - const wethGateWay = await deployWETHGateway([weth], verify); - console.log(`${CONTRACT_NAME}.address`, wethGateWay.address); - - console.log(`\tFinished ${CONTRACT_NAME} deployment`); - }); diff --git a/tasks/full/5-deploy-wethGateWay.ts b/tasks/full/5-deploy-wethGateWay.ts new file mode 100644 index 00000000..279580ef --- /dev/null +++ b/tasks/full/5-deploy-wethGateWay.ts @@ -0,0 +1,32 @@ +import { task } from 'hardhat/config'; +import { AaveConfig } from '../../markets/aave/index'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { loadPoolConfig, ConfigNames } from '../../helpers/configuration'; +import { deployWETHGateway } from '../../helpers/contracts-deployments'; +import { DRE } from '../../helpers/misc-utils'; +import { eEthereumNetwork } from '../../helpers/types'; + +const CONTRACT_NAME = 'WETHGateway'; + +task(`full-deploy-weth-gateway`, `Deploys the ${CONTRACT_NAME} contract`) + .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) + .addFlag('verify', `Verify ${CONTRACT_NAME} contract via Etherscan API.`) + .setAction(async ({ verify, pool }, localBRE) => { + await localBRE.run('set-DRE'); + const network = localBRE.network.name; + const Weth = AaveConfig.ReserveAssets[DRE.network.name].WETH; + const poolConfig = loadPoolConfig(pool); + const { WethGateway } = poolConfig; + + if (!localBRE.network.config.chainId) { + throw new Error('INVALID_CHAIN_ID'); + } + let gateWay = getParamPerNetwork(WethGateway, network); + if (gateWay === '') { + const wethGateWay = await deployWETHGateway([Weth], verify); + console.log(`${CONTRACT_NAME}.address`, wethGateWay.address); + console.log(`\tFinished ${CONTRACT_NAME} deployment`); + } else { + console.log(`Weth gateway already deployed. Address: ${gateWay}`); + } + }); diff --git a/tasks/full/5_initialize.ts b/tasks/full/6-initialize.ts similarity index 93% rename from tasks/full/5_initialize.ts rename to tasks/full/6-initialize.ts index 28439d25..1b949241 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/6-initialize.ts @@ -12,6 +12,7 @@ import { getWethAddress, getTreasuryAddress, } from '../../helpers/configuration'; +import { getWETHGateway } from '../../helpers/contracts-getters'; import { eEthereumNetwork, ICommonConfiguration } from '../../helpers/types'; import { waitForTx } from '../../helpers/misc-utils'; import { initReservesByHelper, configureReservesByHelper } from '../../helpers/init-helpers'; @@ -85,7 +86,11 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') await deployWalletBalancerProvider(verify); const lendingPoolAddress = await addressesProvider.getLendingPool(); - const gateWay = await getParamPerNetwork(WethGateway, network); + + let gateWay = getParamPerNetwork(WethGateway, network); + if (gateWay == '') { + gateWay = (await getWETHGateway()).address; + } await authorizeWETHGateway(gateWay, lendingPoolAddress); } catch (err) { console.error(err); diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index 96bcbbb8..ccf71f3a 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -29,15 +29,18 @@ task('aave:mainnet', 'Deploy development enviroment') console.log('4. Deploy Data Provider'); await DRE.run('full:data-provider', { pool: POOL_NAME }); - console.log('5. Initialize lending pool'); + console.log('5. Deploy weth Gethway provider'); + 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 }); if (verify) { printContracts(); - console.log('4. Veryfing contracts'); + console.log('7. Veryfing contracts'); await DRE.run('verify:general', { all: true, pool: POOL_NAME }); - console.log('5. Veryfing aTokens and debtTokens'); + console.log('8. Veryfing aTokens and debtTokens'); await DRE.run('verify:tokens', { pool: POOL_NAME }); } diff --git a/tasks/verifications/1_general.ts b/tasks/verifications/1_general.ts index 6e42e483..89a54d0d 100644 --- a/tasks/verifications/1_general.ts +++ b/tasks/verifications/1_general.ts @@ -89,10 +89,7 @@ task('verify:general', 'Deploy oracles for dev enviroment') // WETHGateway console.log('\n- Verifying WETHGateway...\n'); - await verifyContract(wethGateway.address, [ - await getWethAddress(poolConfig), - lendingPoolProxy.address, - ]); + await verifyContract(wethGateway.address, [await getWethAddress(poolConfig)]); } // Lending Pool proxy console.log('\n- Verifying Lending Pool Proxy...\n'); From f023ce09c59df3ce105ad0a823bd69f9beb5f299 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 22 Feb 2021 09:57:48 -0500 Subject: [PATCH 139/219] Slight fixed for fork deployment --- tasks/full/5-deploy-wethGateWay.ts | 4 ++-- tasks/migrations/aave.mainnet.ts | 2 +- tasks/migrations/lp.mainnet.ts | 9 ++++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tasks/full/5-deploy-wethGateWay.ts b/tasks/full/5-deploy-wethGateWay.ts index 279580ef..12c97a15 100644 --- a/tasks/full/5-deploy-wethGateWay.ts +++ b/tasks/full/5-deploy-wethGateWay.ts @@ -1,7 +1,7 @@ import { task } from 'hardhat/config'; import { AaveConfig } from '../../markets/aave/index'; import { getParamPerNetwork } from '../../helpers/contracts-helpers'; -import { loadPoolConfig, ConfigNames } from '../../helpers/configuration'; +import { loadPoolConfig, ConfigNames, getWethAddress } from '../../helpers/configuration'; import { deployWETHGateway } from '../../helpers/contracts-deployments'; import { DRE } from '../../helpers/misc-utils'; import { eEthereumNetwork } from '../../helpers/types'; @@ -14,8 +14,8 @@ task(`full-deploy-weth-gateway`, `Deploys the ${CONTRACT_NAME} contract`) .setAction(async ({ verify, pool }, localBRE) => { await localBRE.run('set-DRE'); const network = localBRE.network.name; - const Weth = AaveConfig.ReserveAssets[DRE.network.name].WETH; const poolConfig = loadPoolConfig(pool); + const Weth = await getWethAddress(poolConfig); const { WethGateway } = poolConfig; if (!localBRE.network.config.chainId) { diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index ccf71f3a..fe05938d 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -29,7 +29,7 @@ task('aave:mainnet', 'Deploy development enviroment') console.log('4. Deploy Data Provider'); await DRE.run('full:data-provider', { pool: POOL_NAME }); - console.log('5. Deploy weth Gethway provider'); + console.log('5. Deploy WETH Gateway'); await DRE.run('full-deploy-weth-gateway', { pool: POOL_NAME }); console.log('6. Initialize lending pool'); diff --git a/tasks/migrations/lp.mainnet.ts b/tasks/migrations/lp.mainnet.ts index 912f48b4..4faea738 100644 --- a/tasks/migrations/lp.mainnet.ts +++ b/tasks/migrations/lp.mainnet.ts @@ -29,15 +29,18 @@ task('lp:mainnet', 'Deploy development enviroment') console.log('4. Deploy Data Provider'); await DRE.run('full:data-provider', { pool: POOL_NAME }); - console.log('5. Initialize lending pool'); + 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 }); if (verify) { printContracts(); - console.log('4. Veryfing contracts'); + console.log('7. Veryfing contracts'); await DRE.run('verify:general', { all: true, pool: POOL_NAME }); - console.log('5. Veryfing aTokens and debtTokens'); + console.log('8. Veryfing aTokens and debtTokens'); await DRE.run('verify:tokens', { pool: POOL_NAME }); } From 7f3e78e0b246a375d73048724b4e0f4fd605fc67 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 22 Feb 2021 11:54:50 -0500 Subject: [PATCH 140/219] Updated WETH aggregator address on Matic --- markets/matic/commons.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index 0bc92154..2029fd54 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -168,6 +168,7 @@ export const CommonsConfig: ICommonConfiguration = { USDC: '0xfE4A8cc5b5B2366C1B58Bea3858e81843581b2F7', USDT: '0x0A6513e40db6EB1b165753AD52E80663aeA50545', WBTC: '0xc907E116054Ad103354f2D350FD2514433D57F6f', + WETH: '0xF9680D99D6C9589e2a93a78A04A279e509205945', WMATIC: '0xAB594600376Ec9fD91F8e885dADF0CE036862dE0', }, [eEthereumNetwork.mumbai]: { From baa5de09d0029e94eb28320e26c73facd3b388d0 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 22 Feb 2021 09:59:21 +0100 Subject: [PATCH 141/219] Improved hardhat config --- hardhat.config.ts | 68 +++++++++++----------------------------- helper-hardhat-config.ts | 41 ++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 50 deletions(-) create mode 100644 helper-hardhat-config.ts diff --git a/hardhat.config.ts b/hardhat.config.ts index 030a780d..7f293569 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -3,9 +3,10 @@ import fs from 'fs'; import { HardhatUserConfig } from 'hardhat/types'; // @ts-ignore import { accounts } from './test-wallets.js'; -import { eEthereumNetwork } from './helpers/types'; +import { eEthereumNetwork, iParamsPerNetwork } from './helpers/types'; import { BUIDLEREVM_CHAINID, COVERAGE_CHAINID } from './helpers/buidler-constants'; - +import { NETWORKS_RPC_URL, NETWORKS_DEFAULT_GAS } from './helper-hardhat-config'; + require('dotenv').config(); import '@nomiclabs/hardhat-ethers'; @@ -43,58 +44,25 @@ if (!SKIP_LOAD) { require(`${path.join(__dirname, 'tasks/misc')}/set-bre.ts`); -const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number) => { - const net = networkName === 'main' ? 'mainnet' : networkName; - if (networkName == 'matic') return { - url: 'https://rpc-mainnet.matic.network', - blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, - gasMultiplier: DEFAULT_GAS_MUL, - gasPrice: 7500000000, - chainId: networkId, - accounts: { - mnemonic: MNEMONIC, - path: MNEMONIC_PATH, - initialIndex: 0, - count: 20, - }, - } - if (networkName == 'mumbai') return { - url: 'https://rpc-mumbai.maticvigil.com', - blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, - gasMultiplier: DEFAULT_GAS_MUL, - gasPrice: 1 * 1000 * 1000 * 1000, - chainId: networkId, - accounts: { - mnemonic: MNEMONIC, - path: MNEMONIC_PATH, - initialIndex: 0, - count: 20, - }, - } - return { - url: ALCHEMY_KEY - ? `https://eth-${net}.alchemyapi.io/v2/${ALCHEMY_KEY}` - : `https://${net}.infura.io/v3/${INFURA_KEY}`, - hardfork: HARDFORK, - blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, - gasMultiplier: DEFAULT_GAS_MUL, - gasPrice: DEFAULT_GAS_PRICE, - chainId: networkId, - accounts: { - mnemonic: MNEMONIC, - path: MNEMONIC_PATH, - initialIndex: 0, - count: 20, - }, - }; -}; +const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number) => ({ + url: NETWORKS_RPC_URL[networkName], + hardfork: HARDFORK, + blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, + gasMultiplier: DEFAULT_GAS_MUL, + gasPrice: NETWORKS_DEFAULT_GAS[networkName], + chainId: networkId, + accounts: { + mnemonic: MNEMONIC, + path: MNEMONIC_PATH, + initialIndex: 0, + count: 20, + }, +}); const mainnetFork = MAINNET_FORK ? { blockNumber: 11739065, - url: ALCHEMY_KEY - ? `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}` - : `https://mainnet.infura.io/v3/${INFURA_KEY}`, + url: NETWORKS_RPC_URL['main'], } : undefined; diff --git a/helper-hardhat-config.ts b/helper-hardhat-config.ts new file mode 100644 index 00000000..8c78656d --- /dev/null +++ b/helper-hardhat-config.ts @@ -0,0 +1,41 @@ +// @ts-ignore +import { eEthereumNetwork, iParamsPerNetwork } from './helpers/types'; + +require('dotenv').config(); + +const INFURA_KEY = process.env.INFURA_KEY || ''; +const ALCHEMY_KEY = process.env.ALCHEMY_KEY || ''; + +const GWEI = 1000 * 1000 * 1000; + +export const NETWORKS_RPC_URL: iParamsPerNetwork = { + [eEthereumNetwork.kovan]: ALCHEMY_KEY + ? `https://eth-kovan.alchemyapi.io/v2/${ALCHEMY_KEY}` + : `https://kovan.infura.io/v3/${INFURA_KEY}`, + [eEthereumNetwork.ropsten]: ALCHEMY_KEY + ? `https://eth-ropsten.alchemyapi.io/v2/${ALCHEMY_KEY}` + : `https://ropsten.infura.io/v3/${INFURA_KEY}`, + [eEthereumNetwork.main]: ALCHEMY_KEY + ? `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}` + : `https://mainnet.infura.io/v3/${INFURA_KEY}`, + [eEthereumNetwork.coverage]: 'http://localhost:8555', + [eEthereumNetwork.hardhat]: 'http://localhost:8545', + [eEthereumNetwork.buidlerevm]: 'http://localhost:8545', + [eEthereumNetwork.tenderlyMain]: ALCHEMY_KEY + ? `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}` + : `https://mainnet.infura.io/v3/${INFURA_KEY}`, + [eEthereumNetwork.mumbai]: 'https://rpc-mumbai.maticvigil.com', + [eEthereumNetwork.matic]: 'https://rpc-mainnet.matic.network', +} + +export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { + [eEthereumNetwork.kovan]: 65 * GWEI , + [eEthereumNetwork.ropsten]: 65 * GWEI , + [eEthereumNetwork.main]: 65 * GWEI , + [eEthereumNetwork.coverage]: 65 * GWEI , + [eEthereumNetwork.hardhat]: 65 * GWEI , + [eEthereumNetwork.buidlerevm]: 65 * GWEI , + [eEthereumNetwork.tenderlyMain]: 65 * GWEI , + [eEthereumNetwork.mumbai]: 1 * GWEI , + [eEthereumNetwork.matic]: 65 * GWEI , +} \ No newline at end of file From 06d75ac7c7ba42c2f3d5ceaa626dfc6c86952d52 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 22 Feb 2021 10:44:10 +0100 Subject: [PATCH 142/219] Cleaned up config --- hardhat.config.ts | 3 - helper-hardhat-config.ts | 4 +- helpers/types.ts | 39 +++++---- markets/aave/commons.ts | 70 +++++----------- markets/aave/index.ts | 12 ++- markets/matic/commons.ts | 172 +++++++-------------------------------- markets/matic/index.ts | 29 +------ 7 files changed, 85 insertions(+), 244 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 7f293569..d518905a 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -19,10 +19,7 @@ import '@tenderly/hardhat-tenderly'; const SKIP_LOAD = process.env.SKIP_LOAD === 'true'; const DEFAULT_BLOCK_GAS_LIMIT = 12450000; const DEFAULT_GAS_MUL = 5; -const DEFAULT_GAS_PRICE = 65 * 1000 * 1000 * 1000; const HARDFORK = 'istanbul'; -const INFURA_KEY = process.env.INFURA_KEY || ''; -const ALCHEMY_KEY = process.env.ALCHEMY_KEY || ''; const ETHERSCAN_KEY = process.env.ETHERSCAN_KEY || ''; const MNEMONIC_PATH = "m/44'/60'/0'/0"; const MNEMONIC = process.env.MNEMONIC || ''; diff --git a/helper-hardhat-config.ts b/helper-hardhat-config.ts index 8c78656d..159418e9 100644 --- a/helper-hardhat-config.ts +++ b/helper-hardhat-config.ts @@ -26,6 +26,7 @@ export const NETWORKS_RPC_URL: iParamsPerNetwork = { : `https://mainnet.infura.io/v3/${INFURA_KEY}`, [eEthereumNetwork.mumbai]: 'https://rpc-mumbai.maticvigil.com', [eEthereumNetwork.matic]: 'https://rpc-mainnet.matic.network', + [eEthereumNetwork.xdai]: 'https://rpc.xdaichain.com/', } export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { @@ -37,5 +38,6 @@ export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { [eEthereumNetwork.buidlerevm]: 65 * GWEI , [eEthereumNetwork.tenderlyMain]: 65 * GWEI , [eEthereumNetwork.mumbai]: 1 * GWEI , - [eEthereumNetwork.matic]: 65 * GWEI , + [eEthereumNetwork.matic]: 2 * GWEI , + [eEthereumNetwork.xdai]: 1 * GWEI, } \ No newline at end of file diff --git a/helpers/types.ts b/helpers/types.ts index d8e17fcf..8b6b442d 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -12,8 +12,15 @@ export enum eEthereumNetwork { coverage = 'coverage', hardhat = 'hardhat', tenderlyMain = 'tenderlyMain', +} + +export enum ePolygonNetwork { matic = 'matic', - mumbai = 'mumbai', + mumbai = 'mumbail', +} + +export enum eXDaiNetwork { + xdai = 'xdai', } export enum EthereumNetworkNames { @@ -22,6 +29,7 @@ export enum EthereumNetworkNames { main = 'main', matic = 'matic', mumbai = 'mumbai', + xdai = 'xdai', } export enum AavePools { @@ -378,7 +386,12 @@ export interface IMarketRates { borrowRate: string; } -export interface iParamsPerNetwork { +export type iParamsPerNetwork = + | iEthereumParamsPerNetwork + | iPolygonParamsPerNetwork + | iXDaiParamsPerNetwork; + +export interface iEthereumParamsPerNetwork { [eEthereumNetwork.coverage]: T; [eEthereumNetwork.buidlerevm]: T; [eEthereumNetwork.kovan]: T; @@ -386,8 +399,15 @@ export interface iParamsPerNetwork { [eEthereumNetwork.main]: T; [eEthereumNetwork.hardhat]: T; [eEthereumNetwork.tenderlyMain]: T; - [eEthereumNetwork.mumbai]: T; - [eEthereumNetwork.matic]: T; +} + +export interface iPolygonParamsPerNetwork { + [ePolygonNetwork.matic]: T; + [ePolygonNetwork.mumbai]: T; +} + +export interface iXDaiParamsPerNetwork { + [eXDaiNetwork.xdai]: T; } export interface iParamsPerPool { @@ -411,17 +431,6 @@ export interface ObjectString { [key: string]: string; } -export enum EthereumNetwork { - kovan = 'kovan', - ropsten = 'ropsten', - development = 'development', - main = 'main', - coverage = 'soliditycoverage', - tenderlyMain = 'tenderlyMain', - matic = 'matic', - mumbai = 'mumbai', -} - export interface IProtocolGlobalConfig { TokenDistributorPercentageBase: string; MockUsdPriceInWei: string; diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index 39be628b..da91442d 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -1,6 +1,6 @@ import BigNumber from 'bignumber.js'; import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants'; -import { ICommonConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; +import { ICommonConfiguration, eEthereumNetwork } from '../../helpers/types'; // ---------------- // PROTOCOL GLOBAL PARAMS @@ -105,8 +105,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: undefined, [eEthereumNetwork.main]: undefined, [eEthereumNetwork.tenderlyMain]: undefined, - [eEthereumNetwork.mumbai]: undefined, - [eEthereumNetwork.matic]: undefined, }, PoolAdminIndex: 0, EmergencyAdmin: { @@ -117,8 +115,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: undefined, [eEthereumNetwork.main]: undefined, [eEthereumNetwork.tenderlyMain]: undefined, - [eEthereumNetwork.mumbai]: undefined, - [eEthereumNetwork.matic]: undefined, }, EmergencyAdminIndex: 1, ProviderRegistry: { @@ -129,8 +125,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', }, ProviderRegistryOwner: { [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', @@ -140,8 +134,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', }, LendingRateOracle: { [eEthereumNetwork.coverage]: '', @@ -151,8 +143,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', [eEthereumNetwork.main]: '',//'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', }, LendingPoolCollateralManager: { [eEthereumNetwork.coverage]: '', @@ -162,8 +152,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', }, WethGateway: { [eEthereumNetwork.coverage]: '', @@ -178,42 +166,34 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.hardhat]: '', - [EthereumNetwork.kovan]: '0x971efe90088f21dc6a36f610ffed77fc19710708', - [EthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c', - [EthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', - [EthereumNetwork.tenderlyMain]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', + [eEthereumNetwork.kovan]: '0x971efe90088f21dc6a36f610ffed77fc19710708', + [eEthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c', + [eEthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', + [eEthereumNetwork.tenderlyMain]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', }, AaveOracle: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [EthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', - [EthereumNetwork.ropsten]: ZERO_ADDRESS, - [EthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', - [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', + [eEthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', + [eEthereumNetwork.ropsten]: ZERO_ADDRESS, + [eEthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', + [eEthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', }, FallbackOracle: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [EthereumNetwork.kovan]: '0x50913E8E1c650E790F8a1E741FF9B1B1bB251dfe', - [EthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d', - [EthereumNetwork.main]: ZERO_ADDRESS, - [EthereumNetwork.tenderlyMain]: ZERO_ADDRESS, - [eEthereumNetwork.mumbai]: ZERO_ADDRESS, - [eEthereumNetwork.matic]: ZERO_ADDRESS, + [eEthereumNetwork.kovan]: '0x50913E8E1c650E790F8a1E741FF9B1B1bB251dfe', + [eEthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d', + [eEthereumNetwork.main]: ZERO_ADDRESS, + [eEthereumNetwork.tenderlyMain]: ZERO_ADDRESS, }, ChainlinkAggregator: { [eEthereumNetwork.coverage]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.buidlerevm]: {}, - [eEthereumNetwork.matic]: {}, - [eEthereumNetwork.mumbai]: {}, - [EthereumNetwork.kovan]: { + [eEthereumNetwork.kovan]: { AAVE: '0xd04647B7CB523bb9f26730E9B6dE1174db7591Ad', BAT: '0x0e4fcEC26c9f85c3D714370c98f43C4E02Fc35Ae', BUSD: '0xbF7A18ea5DE0501f7559144e702b29c55b055CcB', @@ -235,7 +215,7 @@ export const CommonsConfig: ICommonConfiguration = { ZRX: '0xBc3f28Ccc21E9b5856E81E6372aFf57307E2E883', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, - [EthereumNetwork.ropsten]: { + [eEthereumNetwork.ropsten]: { AAVE: ZERO_ADDRESS, BAT: '0xafd8186c962daf599f171b8600f3e19af7b52c92', BUSD: '0x0A32D96Ff131cd5c3E0E5AAB645BF009Eda61564', @@ -257,7 +237,7 @@ export const CommonsConfig: ICommonConfiguration = { ZRX: '0x1d0052e4ae5b4ae4563cbac50edc3627ca0460d7', USD: '0x8468b2bDCE073A157E560AA4D9CcF6dB1DB98507', }, - [EthereumNetwork.main]: { + [eEthereumNetwork.main]: { AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', BAT: '0x0d16d4528239e9ee52fa531af613AcdB23D88c94', BUSD: '0x614715d2Af89E6EC99A233818275142cE88d1Cfd', @@ -279,7 +259,7 @@ export const CommonsConfig: ICommonConfiguration = { ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', }, - [EthereumNetwork.tenderlyMain]: { + [eEthereumNetwork.tenderlyMain]: { AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', BAT: '0x0d16d4528239e9ee52fa531af613AcdB23D88c94', BUSD: '0x614715d2Af89E6EC99A233818275142cE88d1Cfd', @@ -306,12 +286,10 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.buidlerevm]: {}, - [EthereumNetwork.main]: {}, - [EthereumNetwork.kovan]: {}, - [EthereumNetwork.ropsten]: {}, - [EthereumNetwork.tenderlyMain]: {}, - [eEthereumNetwork.matic]: {}, - [eEthereumNetwork.mumbai]: {}, + [eEthereumNetwork.main]: {}, + [eEthereumNetwork.kovan]: {}, + [eEthereumNetwork.ropsten]: {}, + [eEthereumNetwork.tenderlyMain]: {}, }, ReservesConfig: {}, ATokenDomainSeparator: { @@ -325,8 +303,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '', [eEthereumNetwork.tenderlyMain]: '', - [EthereumNetwork.mumbai]: '', - [EthereumNetwork.matic]: '', }, WETH: { [eEthereumNetwork.coverage]: '', // deployed in local evm @@ -336,8 +312,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0xc778417e063141139fce010982780140aa0cd5ab', [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', [eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - [EthereumNetwork.mumbai]: '', - [EthereumNetwork.matic]: '', }, ReserveFactorTreasuryAddress: { [eEthereumNetwork.coverage]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', @@ -347,7 +321,5 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.main]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.tenderlyMain]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', - [EthereumNetwork.mumbai]: '', - [EthereumNetwork.matic]: '', }, }; diff --git a/markets/aave/index.ts b/markets/aave/index.ts index 0f4d56c8..88e55a83 100644 --- a/markets/aave/index.ts +++ b/markets/aave/index.ts @@ -1,5 +1,5 @@ import { oneRay, ZERO_ADDRESS } from '../../helpers/constants'; -import { IAaveConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; +import { IAaveConfiguration, eEthereumNetwork } from '../../helpers/types'; import { CommonsConfig } from './commons'; import { @@ -58,9 +58,7 @@ export const AaveConfig: IAaveConfiguration = { [eEthereumNetwork.buidlerevm]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.coverage]: {}, - [eEthereumNetwork.matic]: {}, - [eEthereumNetwork.mumbai]: {}, - [EthereumNetwork.kovan]: { + [eEthereumNetwork.kovan]: { AAVE: '0xB597cd8D3217ea6477232F9217fa70837ff667Af', BAT: '0x2d12186Fbb9f9a8C28B3FfdD4c42920f8539D738', BUSD: '0x4c6E1EFC12FDfD568186b7BAEc0A43fFfb4bCcCf', @@ -82,7 +80,7 @@ export const AaveConfig: IAaveConfiguration = { YFI: '0xb7c325266ec274fEb1354021D27FA3E3379D840d', ZRX: '0xD0d76886cF8D952ca26177EB7CfDf83bad08C00C', }, - [EthereumNetwork.ropsten]: { + [eEthereumNetwork.ropsten]: { AAVE: '', BAT: '0x85B24b3517E3aC7bf72a14516160541A60cFF19d', BUSD: '0xFA6adcFf6A90c11f31Bc9bb59eC0a6efB38381C6', @@ -104,7 +102,7 @@ export const AaveConfig: IAaveConfiguration = { YFI: ZERO_ADDRESS, ZRX: '0x02d7055704EfF050323A2E5ee4ba05DB2A588959', }, - [EthereumNetwork.main]: { + [eEthereumNetwork.main]: { AAVE: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', BAT: '0x0d8775f648430679a709e98d2b0cb6250d2887ef', BUSD: '0x4Fabb145d64652a948d72533023f6E7A623C7C53', @@ -126,7 +124,7 @@ export const AaveConfig: IAaveConfiguration = { YFI: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', ZRX: '0xE41d2489571d322189246DaFA5ebDe1F4699F498', }, - [EthereumNetwork.tenderlyMain]: { + [eEthereumNetwork.tenderlyMain]: { AAVE: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', BAT: '0x0d8775f648430679a709e98d2b0cb6250d2887ef', BUSD: '0x4Fabb145d64652a948d72533023f6E7A623C7C53', diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index 2029fd54..7dfed41f 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -1,6 +1,6 @@ import BigNumber from 'bignumber.js'; import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants'; -import { ICommonConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; +import { ICommonConfiguration, ePolygonNetwork } from '../../helpers/types'; // ---------------- // PROTOCOL GLOBAL PARAMS @@ -58,112 +58,45 @@ export const CommonsConfig: ICommonConfiguration = { // If PoolAdmin/emergencyAdmin is set, will take priority over PoolAdminIndex/emergencyAdminIndex PoolAdmin: { - [eEthereumNetwork.coverage]: undefined, - [eEthereumNetwork.buidlerevm]: undefined, - [eEthereumNetwork.coverage]: undefined, - [eEthereumNetwork.hardhat]: undefined, - [eEthereumNetwork.kovan]: undefined, - [eEthereumNetwork.ropsten]: undefined, - [eEthereumNetwork.main]: undefined, - [eEthereumNetwork.tenderlyMain]: undefined, - [eEthereumNetwork.mumbai]: undefined, - [eEthereumNetwork.matic]: undefined, + [ePolygonNetwork.mumbai]: undefined, + [ePolygonNetwork.matic]: undefined, }, PoolAdminIndex: 0, EmergencyAdmin: { - [eEthereumNetwork.hardhat]: undefined, - [eEthereumNetwork.coverage]: undefined, - [eEthereumNetwork.buidlerevm]: undefined, - [eEthereumNetwork.kovan]: undefined, - [eEthereumNetwork.ropsten]: undefined, - [eEthereumNetwork.main]: undefined, - [eEthereumNetwork.tenderlyMain]: undefined, - [eEthereumNetwork.mumbai]: undefined, - [eEthereumNetwork.matic]: undefined, + [ePolygonNetwork.mumbai]: undefined, + [ePolygonNetwork.matic]: undefined, }, EmergencyAdminIndex: 1, ProviderRegistry: { - [eEthereumNetwork.kovan]: '0x1E40B561EC587036f9789aF83236f057D1ed2A90', - [eEthereumNetwork.ropsten]: '', - [eEthereumNetwork.main]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', - [eEthereumNetwork.coverage]: '', - [eEthereumNetwork.hardhat]: '', - [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', - [eEthereumNetwork.mumbai]: '0x569859d41499B4dDC28bfaA43915051FF0A38a6F', // TEMP - [eEthereumNetwork.matic]: '0x28334e4791860a0c1eCF89a62B973ba04a5d643F', // TEMP + [ePolygonNetwork.mumbai]: '0x569859d41499B4dDC28bfaA43915051FF0A38a6F', // TEMP + [ePolygonNetwork.matic]: '0x28334e4791860a0c1eCF89a62B973ba04a5d643F', // TEMP }, ProviderRegistryOwner: { - [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', - [eEthereumNetwork.ropsten]: '', - [eEthereumNetwork.main]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', - [eEthereumNetwork.coverage]: '', - [eEthereumNetwork.hardhat]: '', - [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', - [eEthereumNetwork.mumbai]: '0x18d9bA2baEfBdE0FF137C4ad031427EF205f1Fd9', // TEMP - [eEthereumNetwork.matic]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', // TEMP + [ePolygonNetwork.mumbai]: '0x18d9bA2baEfBdE0FF137C4ad031427EF205f1Fd9', // TEMP + [ePolygonNetwork.matic]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', // TEMP }, LendingRateOracle: { - [eEthereumNetwork.coverage]: '', - [eEthereumNetwork.hardhat]: '', - [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '',//'0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', - [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', - [eEthereumNetwork.main]: '',//'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', - [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', + [ePolygonNetwork.mumbai]: '', + [ePolygonNetwork.matic]: '', }, LendingPoolCollateralManager: { - [eEthereumNetwork.coverage]: '', - [eEthereumNetwork.hardhat]: '', - [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '0x9269b6453d0d75370c4c85e5a42977a53efdb72a', - [eEthereumNetwork.ropsten]: '', - [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', - [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', + [ePolygonNetwork.mumbai]: '', + [ePolygonNetwork.matic]: '', }, TokenDistributor: { - [eEthereumNetwork.coverage]: '', - [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.hardhat]: '', - [EthereumNetwork.kovan]: '0x971efe90088f21dc6a36f610ffed77fc19710708', - [EthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c', - [EthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', - [EthereumNetwork.tenderlyMain]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', + [ePolygonNetwork.mumbai]: '', + [ePolygonNetwork.matic]: '', }, AaveOracle: { - [eEthereumNetwork.coverage]: '', - [eEthereumNetwork.hardhat]: '', - [eEthereumNetwork.buidlerevm]: '', - [EthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', - [EthereumNetwork.ropsten]: ZERO_ADDRESS, - [EthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', - [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', + [ePolygonNetwork.mumbai]: '', + [ePolygonNetwork.matic]: '', }, FallbackOracle: { - [eEthereumNetwork.coverage]: '', - [eEthereumNetwork.hardhat]: '', - [eEthereumNetwork.buidlerevm]: '', - [EthereumNetwork.kovan]: '0x50913E8E1c650E790F8a1E741FF9B1B1bB251dfe', - [EthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d', - [EthereumNetwork.main]: ZERO_ADDRESS, - [EthereumNetwork.tenderlyMain]: ZERO_ADDRESS, - [eEthereumNetwork.mumbai]: ZERO_ADDRESS, - [eEthereumNetwork.matic]: ZERO_ADDRESS, + [ePolygonNetwork.mumbai]: ZERO_ADDRESS, + [ePolygonNetwork.matic]: ZERO_ADDRESS, }, ChainlinkAggregator: { - [eEthereumNetwork.coverage]: {}, - [eEthereumNetwork.hardhat]: {}, - [eEthereumNetwork.buidlerevm]: {}, - [eEthereumNetwork.matic]: { + [ePolygonNetwork.matic]: { DAI: '0x4746DeC9e833A82EC7C2C1356372CcF2cfcD2F3D', USDC: '0xfE4A8cc5b5B2366C1B58Bea3858e81843581b2F7', USDT: '0x0A6513e40db6EB1b165753AD52E80663aeA50545', @@ -171,76 +104,29 @@ export const CommonsConfig: ICommonConfiguration = { WETH: '0xF9680D99D6C9589e2a93a78A04A279e509205945', WMATIC: '0xAB594600376Ec9fD91F8e885dADF0CE036862dE0', }, - [eEthereumNetwork.mumbai]: { + [ePolygonNetwork.mumbai]: { DAI: ZERO_ADDRESS, USDC: ZERO_ADDRESS, USDT: ZERO_ADDRESS, WBTC: ZERO_ADDRESS, WMATIC: ZERO_ADDRESS, }, - [EthereumNetwork.kovan]: {}, - [EthereumNetwork.ropsten]: {}, - [EthereumNetwork.main]: { - DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', - USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', - USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', - WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', - WMATIC: ZERO_ADDRESS, - }, - [EthereumNetwork.tenderlyMain]: { - DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', - USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', - USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', - WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', - WMATIC: ZERO_ADDRESS, - }, }, ReserveAssets: { - [eEthereumNetwork.coverage]: {}, - [eEthereumNetwork.hardhat]: {}, - [eEthereumNetwork.buidlerevm]: {}, - [EthereumNetwork.main]: {}, - [EthereumNetwork.kovan]: {}, - [EthereumNetwork.ropsten]: {}, - [EthereumNetwork.tenderlyMain]: {}, - [eEthereumNetwork.matic]: {}, - [eEthereumNetwork.mumbai]: {}, + [ePolygonNetwork.matic]: {}, + [ePolygonNetwork.mumbai]: {}, }, ReservesConfig: {}, ATokenDomainSeparator: { - [eEthereumNetwork.coverage]: - '0x95b73a72c6ecf4ccbbba5178800023260bad8e75cdccdb8e4827a2977a37c820', - [eEthereumNetwork.hardhat]: - '0xbae024d959c6a022dc5ed37294cd39c141034b2ae5f02a955cce75c930a81bf5', - [eEthereumNetwork.buidlerevm]: - '0xbae024d959c6a022dc5ed37294cd39c141034b2ae5f02a955cce75c930a81bf5', - [eEthereumNetwork.kovan]: '', - [eEthereumNetwork.ropsten]: '', - [eEthereumNetwork.main]: '', - [eEthereumNetwork.tenderlyMain]: '', - [EthereumNetwork.mumbai]: '', - [EthereumNetwork.matic]: '', + [ePolygonNetwork.mumbai]: '', + [ePolygonNetwork.matic]: '', }, WETH: { - [eEthereumNetwork.coverage]: '', // deployed in local evm - [eEthereumNetwork.hardhat]: '', // deployed in local evm - [eEthereumNetwork.buidlerevm]: '', // deployed in local evm - [eEthereumNetwork.kovan]: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', - [eEthereumNetwork.ropsten]: '0xc778417e063141139fce010982780140aa0cd5ab', - [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - [eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - [EthereumNetwork.mumbai]: '0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889', // WMATIC address (untested) - [EthereumNetwork.matic]: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', // WMATIC address + [ePolygonNetwork.mumbai]: '0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889', // WMATIC address (untested) + [ePolygonNetwork.matic]: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', // WMATIC address }, ReserveFactorTreasuryAddress: { - [eEthereumNetwork.coverage]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', - [eEthereumNetwork.hardhat]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', - [eEthereumNetwork.buidlerevm]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', - [eEthereumNetwork.kovan]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', - [eEthereumNetwork.ropsten]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', - [eEthereumNetwork.main]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', - [eEthereumNetwork.tenderlyMain]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', - [EthereumNetwork.mumbai]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', // TEMP - [EthereumNetwork.matic]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', // TEMP + [ePolygonNetwork.mumbai]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', // TEMP + [ePolygonNetwork.matic]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', // TEMP }, }; diff --git a/markets/matic/index.ts b/markets/matic/index.ts index ae935313..cc1484ae 100644 --- a/markets/matic/index.ts +++ b/markets/matic/index.ts @@ -1,5 +1,5 @@ import { oneRay, ZERO_ADDRESS } from '../../helpers/constants'; -import { IMaticConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; +import { IMaticConfiguration, ePolygonNetwork } from '../../helpers/types'; import { CommonsConfig } from './commons'; import { @@ -28,10 +28,7 @@ export const MaticConfig: IMaticConfiguration = { WMATIC: strategyMATIC, }, ReserveAssets: { - [eEthereumNetwork.buidlerevm]: {}, - [eEthereumNetwork.hardhat]: {}, - [eEthereumNetwork.coverage]: {}, - [eEthereumNetwork.matic]: { + [ePolygonNetwork.matic]: { DAI: '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063', USDC: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', USDT: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F', @@ -39,7 +36,7 @@ export const MaticConfig: IMaticConfiguration = { WETH: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', WMATIC: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', }, - [eEthereumNetwork.mumbai]: { // Mock tokens with a simple "mint" external function, except wmatic + [ePolygonNetwork.mumbai]: { // Mock tokens with a simple "mint" external function, except wmatic DAI: '0x13b3fda609C1eeb23b4F4b69257840760dCa6C4a', USDC: '0x52b63223994433FdE2F1350Ba69Dfd2779f06ABA', USDT: '0xB3abd1912F586fDFFa13606882c28E27913853d2', @@ -47,26 +44,6 @@ export const MaticConfig: IMaticConfiguration = { WETH: '0x53CDb16B8C031B779e996406546614E5F05BC4Bf', WMATIC: '0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889', }, - [EthereumNetwork.kovan]: {}, - [EthereumNetwork.ropsten]: {}, - [EthereumNetwork.main]: { - // WMATIC DOES NOT EXIST ON MAIN - DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', - WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', - WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - WMATIC: '0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', - }, - [EthereumNetwork.tenderlyMain]: { - // WMATIC DOES NOT EXIST ON MAIN - DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', - WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', - WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - WMATIC: '0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', - }, }, }; From 42499c527fd69e775eae5cb81acfd3da2281bb71 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 22 Feb 2021 10:55:36 +0100 Subject: [PATCH 143/219] updated hardhat config with new chains --- hardhat.config.ts | 9 +++++---- helper-hardhat-config.ts | 14 +++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index d518905a..3db6b821 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -3,7 +3,7 @@ import fs from 'fs'; import { HardhatUserConfig } from 'hardhat/types'; // @ts-ignore import { accounts } from './test-wallets.js'; -import { eEthereumNetwork, iParamsPerNetwork } from './helpers/types'; +import { eEthereumNetwork, ePolygonNetwork, eXDaiNetwork } from './helpers/types'; import { BUIDLEREVM_CHAINID, COVERAGE_CHAINID } from './helpers/buidler-constants'; import { NETWORKS_RPC_URL, NETWORKS_DEFAULT_GAS } from './helper-hardhat-config'; @@ -41,7 +41,7 @@ if (!SKIP_LOAD) { require(`${path.join(__dirname, 'tasks/misc')}/set-bre.ts`); -const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number) => ({ +const getCommonNetworkConfig = (networkName: eEthereumNetwork | ePolygonNetwork | eXDaiNetwork, networkId: number) => ({ url: NETWORKS_RPC_URL[networkName], hardfork: HARDFORK, blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, @@ -95,8 +95,9 @@ const buidlerConfig: HardhatUserConfig = { ropsten: getCommonNetworkConfig(eEthereumNetwork.ropsten, 3), main: getCommonNetworkConfig(eEthereumNetwork.main, 1), tenderlyMain: getCommonNetworkConfig(eEthereumNetwork.main, 1), - matic: getCommonNetworkConfig(eEthereumNetwork.matic, 137), - mumbai: getCommonNetworkConfig(eEthereumNetwork.mumbai, 80001), + matic: getCommonNetworkConfig(ePolygonNetwork.matic, 137), + mumbai: getCommonNetworkConfig(ePolygonNetwork.mumbai, 80001), + xdai: getCommonNetworkConfig(eXDaiNetwork.xdai, 100), hardhat: { hardfork: 'istanbul', blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, diff --git a/helper-hardhat-config.ts b/helper-hardhat-config.ts index 159418e9..c25f7b9f 100644 --- a/helper-hardhat-config.ts +++ b/helper-hardhat-config.ts @@ -1,5 +1,5 @@ // @ts-ignore -import { eEthereumNetwork, iParamsPerNetwork } from './helpers/types'; +import { eEthereumNetwork, ePolygonNetwork, eXDaiNetwork, iParamsPerNetwork } from './helpers/types'; require('dotenv').config(); @@ -24,9 +24,9 @@ export const NETWORKS_RPC_URL: iParamsPerNetwork = { [eEthereumNetwork.tenderlyMain]: ALCHEMY_KEY ? `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}` : `https://mainnet.infura.io/v3/${INFURA_KEY}`, - [eEthereumNetwork.mumbai]: 'https://rpc-mumbai.maticvigil.com', - [eEthereumNetwork.matic]: 'https://rpc-mainnet.matic.network', - [eEthereumNetwork.xdai]: 'https://rpc.xdaichain.com/', + [ePolygonNetwork.mumbai]: 'https://rpc-mumbai.maticvigil.com', + [ePolygonNetwork.matic]: 'https://rpc-mainnet.matic.network', + [eXDaiNetwork.xdai]: 'https://rpc.xdaichain.com/', } export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { @@ -37,7 +37,7 @@ export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { [eEthereumNetwork.hardhat]: 65 * GWEI , [eEthereumNetwork.buidlerevm]: 65 * GWEI , [eEthereumNetwork.tenderlyMain]: 65 * GWEI , - [eEthereumNetwork.mumbai]: 1 * GWEI , - [eEthereumNetwork.matic]: 2 * GWEI , - [eEthereumNetwork.xdai]: 1 * GWEI, + [ePolygonNetwork.mumbai]: 1 * GWEI , + [ePolygonNetwork.matic]: 2 * GWEI , + [eXDaiNetwork.xdai]: 1 * GWEI, } \ No newline at end of file From c072f3c8e04c958a351b587d7839d3875ef60c77 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 22 Feb 2021 11:05:36 -0500 Subject: [PATCH 144/219] Updated LP config --- markets/lp/commons.ts | 70 +++++++++++++------------------------------ markets/lp/index.ts | 12 ++++---- 2 files changed, 26 insertions(+), 56 deletions(-) diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index 1b7f403a..9c7ca2ee 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -1,6 +1,6 @@ import BigNumber from 'bignumber.js'; import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants'; -import { ICommonConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; +import { ICommonConfiguration, eEthereumNetwork } from '../../helpers/types'; // ---------------- // PROTOCOL GLOBAL PARAMS @@ -108,8 +108,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: undefined, [eEthereumNetwork.main]: undefined, [eEthereumNetwork.tenderlyMain]: undefined, - [eEthereumNetwork.mumbai]: undefined, - [eEthereumNetwork.matic]: undefined, }, PoolAdminIndex: 0, EmergencyAdmin: { @@ -120,8 +118,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: undefined, [eEthereumNetwork.main]: undefined, [eEthereumNetwork.tenderlyMain]: undefined, - [eEthereumNetwork.mumbai]: undefined, - [eEthereumNetwork.matic]: undefined, }, EmergencyAdminIndex: 1, ProviderRegistry: { @@ -132,8 +128,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', }, ProviderRegistryOwner: { // DEPLOYED WITH CORRECT ADDRESS [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', @@ -143,8 +137,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', }, LendingRateOracle: { [eEthereumNetwork.coverage]: '', @@ -154,8 +146,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', [eEthereumNetwork.main]: '', //'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', // Need to re-deploy because of onlyOwner [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', }, LendingPoolCollateralManager: { [eEthereumNetwork.coverage]: '', @@ -165,8 +155,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', }, WethGateway: { [eEthereumNetwork.coverage]: '', @@ -181,40 +169,34 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.hardhat]: '', - [EthereumNetwork.kovan]: '0x971efe90088f21dc6a36f610ffed77fc19710708', - [EthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c', - [EthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', - [EthereumNetwork.tenderlyMain]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', + [eEthereumNetwork.kovan]: '0x971efe90088f21dc6a36f610ffed77fc19710708', + [eEthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c', + [eEthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', + [eEthereumNetwork.tenderlyMain]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae', }, AaveOracle: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [EthereumNetwork.kovan]: '0x8fb777d67e9945e2c01936e319057f9d41d559e6', // Need to re-deploy because of onlyOwner - [EthereumNetwork.ropsten]: ZERO_ADDRESS, - [EthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', // Need to re-deploy because of onlyOwner - [EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', + [eEthereumNetwork.kovan]: '0x8fb777d67e9945e2c01936e319057f9d41d559e6', // Need to re-deploy because of onlyOwner + [eEthereumNetwork.ropsten]: ZERO_ADDRESS, + [eEthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', // Need to re-deploy because of onlyOwner + [eEthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', }, FallbackOracle: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [EthereumNetwork.kovan]: '0x50913E8E1c650E790F8a1E741FF9B1B1bB251dfe', - [EthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d', - [EthereumNetwork.main]: ZERO_ADDRESS, - [EthereumNetwork.tenderlyMain]: ZERO_ADDRESS, - [eEthereumNetwork.mumbai]: ZERO_ADDRESS, - [eEthereumNetwork.matic]: ZERO_ADDRESS, + [eEthereumNetwork.kovan]: '0x50913E8E1c650E790F8a1E741FF9B1B1bB251dfe', + [eEthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d', + [eEthereumNetwork.main]: ZERO_ADDRESS, + [eEthereumNetwork.tenderlyMain]: ZERO_ADDRESS, }, ChainlinkAggregator: { [eEthereumNetwork.coverage]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.buidlerevm]: {}, - [EthereumNetwork.kovan]: { + [eEthereumNetwork.kovan]: { USDT: '0x0bF499444525a23E7Bb61997539725cA2e928138', WBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', USDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', @@ -236,9 +218,9 @@ export const CommonsConfig: ICommonConfiguration = { BptWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, - [EthereumNetwork.ropsten]: { + [eEthereumNetwork.ropsten]: { }, - [EthereumNetwork.main]: { + [eEthereumNetwork.main]: { USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', @@ -260,7 +242,7 @@ export const CommonsConfig: ICommonConfiguration = { BptWBTCWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, - [EthereumNetwork.tenderlyMain]: { + [eEthereumNetwork.tenderlyMain]: { USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', @@ -282,19 +264,15 @@ export const CommonsConfig: ICommonConfiguration = { BptWBTCWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, - [eEthereumNetwork.mumbai]: {}, - [eEthereumNetwork.matic]: {}, }, ReserveAssets: { [eEthereumNetwork.coverage]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.buidlerevm]: {}, - [EthereumNetwork.main]: {}, - [EthereumNetwork.kovan]: {}, - [EthereumNetwork.ropsten]: {}, - [EthereumNetwork.tenderlyMain]: {}, - [eEthereumNetwork.mumbai]: {}, - [eEthereumNetwork.matic]: {}, + [eEthereumNetwork.main]: {}, + [eEthereumNetwork.kovan]: {}, + [eEthereumNetwork.ropsten]: {}, + [eEthereumNetwork.tenderlyMain]: {}, }, ReservesConfig: {}, ATokenDomainSeparator: { @@ -308,8 +286,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '', [eEthereumNetwork.tenderlyMain]: '', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', }, WETH: { [eEthereumNetwork.coverage]: '', // deployed in local evm @@ -319,8 +295,6 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0xc778417e063141139fce010982780140aa0cd5ab', [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', [eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', }, ReserveFactorTreasuryAddress: { [eEthereumNetwork.coverage]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', @@ -330,7 +304,5 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.ropsten]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.main]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.tenderlyMain]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', - [eEthereumNetwork.mumbai]: '', - [eEthereumNetwork.matic]: '', }, }; diff --git a/markets/lp/index.ts b/markets/lp/index.ts index d802f372..aeb3bbc7 100644 --- a/markets/lp/index.ts +++ b/markets/lp/index.ts @@ -1,5 +1,5 @@ import { oneRay, ZERO_ADDRESS } from '../../helpers/constants'; -import { ILpConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; +import { ILpConfiguration, eEthereumNetwork } from '../../helpers/types'; import { CommonsConfig } from './commons'; import { @@ -58,9 +58,7 @@ export const lpConfig: ILpConfiguration = { [eEthereumNetwork.buidlerevm]: {}, [eEthereumNetwork.hardhat]: {}, [eEthereumNetwork.coverage]: {}, - [eEthereumNetwork.matic]: {}, - [eEthereumNetwork.mumbai]: {}, - [EthereumNetwork.kovan]: { + [eEthereumNetwork.kovan]: { DAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD', USDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422', USDT: '0x13512979ADE267AB5100878E2e0f485B568328a4', @@ -82,9 +80,9 @@ export const lpConfig: ILpConfiguration = { UniYFIWETH: '0x5af95ddFACC150a1695A3Fc606459fd0dE57b91f', BptWBTCWETH: '0x110569E3261bC0934dA637b019f6f1b6F50ec574', }, - [EthereumNetwork.ropsten]: { + [eEthereumNetwork.ropsten]: { }, - [EthereumNetwork.main]: { + [eEthereumNetwork.main]: { DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', @@ -106,7 +104,7 @@ export const lpConfig: ILpConfiguration = { UniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', BptWBTCWETH: '0x1efF8aF5D577060BA4ac8A29A13525bb0Ee2A3D5', }, - [EthereumNetwork.tenderlyMain]: { + [eEthereumNetwork.tenderlyMain]: { DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7', From 32a0aef1a95fe108a158d1832139d5ef9839ea8b Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 22 Feb 2021 17:51:57 +0100 Subject: [PATCH 145/219] Added wethgateway config to matic --- markets/matic/commons.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index 7dfed41f..b92a1eb6 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -87,6 +87,10 @@ export const CommonsConfig: ICommonConfiguration = { [ePolygonNetwork.mumbai]: '', [ePolygonNetwork.matic]: '', }, + WethGateway: { + [ePolygonNetwork.mumbai]: '', + [ePolygonNetwork.matic]: '', + }, AaveOracle: { [ePolygonNetwork.mumbai]: '', [ePolygonNetwork.matic]: '', From c1142d481051f20d082061c45e4966ba1961c9fa Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 22 Feb 2021 15:59:51 -0500 Subject: [PATCH 146/219] Changed "Lp"/"lp" prefix to "Amm"/"amm" --- helpers/configuration.ts | 12 +- helpers/contracts-getters.ts | 2 +- helpers/contracts-helpers.ts | 6 +- helpers/init-helpers.ts | 8 +- helpers/types.ts | 16 +- markets/aave/commons.ts | 5 - markets/{lp => amm}/commons.ts | 0 markets/{lp => amm}/index.ts | 8 +- markets/{lp => amm}/rateStrategies.ts | 4 +- markets/{lp => amm}/reservesConfigs.ts | 30 +- package-lock.json | 25497 +--------------- package.json | 10 +- .../{lp.mainnet.ts => amm.mainnet.ts} | 4 +- .../{test-lp => test-amm}/__setup.spec.ts | 24 +- .../addresses-provider-registry.spec.ts | 0 .../atoken-modifiers.spec.ts | 0 .../atoken-permit.spec.ts | 0 .../atoken-transfer.spec.ts | 2 +- .../configurator.spec.ts | 2 +- .../delegation-aware-atoken.spec.ts | 4 +- .../{test-lp => test-amm}/flashloan.spec.ts | 0 .../{test-lp => test-amm}/helpers/actions.ts | 0 .../helpers/almost-equal.ts | 0 .../helpers/make-suite.ts | 4 +- .../helpers/scenario-engine.ts | 0 .../helpers/scenarios/borrow-negatives.json | 0 .../scenarios/borrow-repay-stable.json | 0 .../scenarios/borrow-repay-variable.json | 0 .../helpers/scenarios/credit-delegation.json | 0 .../helpers/scenarios/deposit.json | 0 .../scenarios/rebalance-stable-rate.json | 0 .../scenarios/set-use-as-collateral.json | 0 .../helpers/scenarios/swap-rate-mode.json | 0 .../helpers/scenarios/withdraw-negatives.json | 0 .../helpers/scenarios/withdraw.json | 0 .../helpers/utils/calculations.ts | 0 .../helpers/utils/helpers.ts | 0 .../helpers/utils/interfaces/index.ts | 0 .../helpers/utils/math.ts | 0 .../lending-pool-addresses-provider.spec.ts | 0 .../liquidation-atoken.spec.ts | 0 .../liquidation-underlying.spec.ts | 2 +- .../mainnet/check-list.spec.ts | 0 .../pausable-functions.spec.ts | 0 .../pool-modifiers.spec.ts | 0 .../rate-strategy.spec.ts | 0 .../{test-lp => test-amm}/scenario.spec.ts | 4 +- .../stable-rate-economy.spec.ts | 0 .../stable-token.spec.ts | 0 .../subgraph-scenarios.spec.ts | 2 +- .../uniswapAdapters.base.spec.ts | 0 .../uniswapAdapters.flashLiquidation.spec.ts | 0 .../uniswapAdapters.liquiditySwap.spec.ts | 0 .../uniswapAdapters.repay.spec.ts | 0 .../upgradeability.spec.ts | 0 .../variable-debt-token.spec.ts | 0 .../weth-gateway.spec.ts | 0 57 files changed, 194 insertions(+), 25452 deletions(-) rename markets/{lp => amm}/commons.ts (100%) rename markets/{lp => amm}/index.ts (96%) rename markets/{lp => amm}/rateStrategies.ts (94%) rename markets/{lp => amm}/reservesConfigs.ts (92%) rename tasks/migrations/{lp.mainnet.ts => amm.mainnet.ts} (94%) rename test-suites/{test-lp => test-amm}/__setup.spec.ts (93%) rename test-suites/{test-lp => test-amm}/addresses-provider-registry.spec.ts (100%) rename test-suites/{test-lp => test-amm}/atoken-modifiers.spec.ts (100%) rename test-suites/{test-lp => test-amm}/atoken-permit.spec.ts (100%) rename test-suites/{test-lp => test-amm}/atoken-transfer.spec.ts (98%) rename test-suites/{test-lp => test-amm}/configurator.spec.ts (99%) rename test-suites/{test-lp => test-amm}/delegation-aware-atoken.spec.ts (96%) rename test-suites/{test-lp => test-amm}/flashloan.spec.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/actions.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/almost-equal.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/make-suite.ts (98%) rename test-suites/{test-lp => test-amm}/helpers/scenario-engine.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/borrow-negatives.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/borrow-repay-stable.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/borrow-repay-variable.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/credit-delegation.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/deposit.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/rebalance-stable-rate.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/set-use-as-collateral.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/swap-rate-mode.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/withdraw-negatives.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/withdraw.json (100%) rename test-suites/{test-lp => test-amm}/helpers/utils/calculations.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/utils/helpers.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/utils/interfaces/index.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/utils/math.ts (100%) rename test-suites/{test-lp => test-amm}/lending-pool-addresses-provider.spec.ts (100%) rename test-suites/{test-lp => test-amm}/liquidation-atoken.spec.ts (100%) rename test-suites/{test-lp => test-amm}/liquidation-underlying.spec.ts (99%) rename test-suites/{test-lp => test-amm}/mainnet/check-list.spec.ts (100%) rename test-suites/{test-lp => test-amm}/pausable-functions.spec.ts (100%) rename test-suites/{test-lp => test-amm}/pool-modifiers.spec.ts (100%) rename test-suites/{test-lp => test-amm}/rate-strategy.spec.ts (100%) rename test-suites/{test-lp => test-amm}/scenario.spec.ts (93%) rename test-suites/{test-lp => test-amm}/stable-rate-economy.spec.ts (100%) rename test-suites/{test-lp => test-amm}/stable-token.spec.ts (100%) rename test-suites/{test-lp => test-amm}/subgraph-scenarios.spec.ts (96%) rename test-suites/{test-lp => test-amm}/uniswapAdapters.base.spec.ts (100%) rename test-suites/{test-lp => test-amm}/uniswapAdapters.flashLiquidation.spec.ts (100%) rename test-suites/{test-lp => test-amm}/uniswapAdapters.liquiditySwap.spec.ts (100%) rename test-suites/{test-lp => test-amm}/uniswapAdapters.repay.spec.ts (100%) rename test-suites/{test-lp => test-amm}/upgradeability.spec.ts (100%) rename test-suites/{test-lp => test-amm}/variable-debt-token.spec.ts (100%) rename test-suites/{test-lp => test-amm}/weth-gateway.spec.ts (100%) diff --git a/helpers/configuration.ts b/helpers/configuration.ts index a9b780fb..2400d841 100644 --- a/helpers/configuration.ts +++ b/helpers/configuration.ts @@ -8,7 +8,7 @@ import { } from './types'; import { getParamPerPool } from './contracts-helpers'; import AaveConfig from '../markets/aave'; -import LpConfig from '../markets/lp'; +import AmmConfig from '../markets/amm'; import { CommonsConfig } from '../markets/aave/commons'; import { DRE, filterMapBy } from './misc-utils'; import { tEthereumAddress } from './types'; @@ -18,15 +18,15 @@ import { deployWETHMocked } from './contracts-deployments'; export enum ConfigNames { Commons = 'Commons', Aave = 'Aave', - Lp = 'Lp', + Amm = 'Amm', } export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => { switch (configName) { case ConfigNames.Aave: return AaveConfig; - case ConfigNames.Lp: - return LpConfig; + case ConfigNames.Amm: + return AmmConfig; case ConfigNames.Commons: return CommonsConfig; default: @@ -44,8 +44,8 @@ export const getReservesConfigByPool = (pool: AavePools): iMultiPoolsAssets { - const { ETH, USD, WETH, LpWETH, ...assetsAddressesWithoutEth } = allAssetsAddresses; + const { ETH, USD, WETH, ...assetsAddressesWithoutEth } = allAssetsAddresses; const pairs = Object.entries(assetsAddressesWithoutEth).map(([tokenSymbol, tokenAddress]) => { //if (true/*tokenSymbol !== 'WETH' && tokenSymbol !== 'ETH' && tokenSymbol !== 'LpWETH'*/) { diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 21def650..daeaa588 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -159,12 +159,12 @@ export const getParamPerNetwork = ( } }; -export const getParamPerPool = ({ proto, lp }: iParamsPerPool, pool: AavePools) => { +export const getParamPerPool = ({ proto, amm }: iParamsPerPool, pool: AavePools) => { switch (pool) { case AavePools.proto: return proto; - case AavePools.lp: - return lp; + case AavePools.amm: + return amm; default: return proto; } diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 3f6ce5f4..023a1f39 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -212,7 +212,7 @@ export const initReservesByHelper = async ( const chunkedInitInputParams = chunk(initInputParams, initChunks); const configurator = await getLendingPoolConfiguratorProxy(); - await waitForTx(await addressProvider.setPoolAdmin(admin)); + //await waitForTx(await addressProvider.setPoolAdmin(admin)); console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) { @@ -383,7 +383,7 @@ export const initTokenReservesByHelper = async ( const poolAddress = await addressProvider.getLendingPool(); // Set aTokenAndRatesDeployer as temporal admin - await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address)); + //await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address)); // CHUNK CONFIGURATION const initChunks = 4; @@ -563,7 +563,7 @@ export const initTokenReservesByHelper = async ( const chunkedInitInputParams = chunk(initInputParams, initChunks); const configurator = await getLendingPoolConfiguratorProxy(); - await waitForTx(await addressProvider.setPoolAdmin(admin)); + //await waitForTx(await addressProvider.setPoolAdmin(admin)); console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) { @@ -576,7 +576,7 @@ export const initTokenReservesByHelper = async ( } // Set deployer back as admin - await waitForTx(await addressProvider.setPoolAdmin(admin)); + //await waitForTx(await addressProvider.setPoolAdmin(admin)); return gasUsage; // No longer relevant }; diff --git a/helpers/types.ts b/helpers/types.ts index 76557658..3a3f9a99 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -22,7 +22,7 @@ export enum EthereumNetworkNames { export enum AavePools { proto = 'proto', - lp = 'lp', + amm = 'amm', } export enum eContractid { @@ -205,11 +205,6 @@ export interface iAssetBase { USD: T; REN: T; ENJ: T; - // LpWETH: T; - // LpWBTC: T; - // LpDAI: T; - // LpUSDC: T; - // LpUSDT: T; UniDAIWETH: T; UniWBTCWETH: T; UniAAVEWETH: T; @@ -307,11 +302,6 @@ export enum TokenContractId { YFI = 'YFI', UNI = 'UNI', ENJ = 'ENJ', - // LpWETH = 'LpWETH', - // LpWBTC = 'LpWBTC', - // LpDAI = 'LpDAI', - // LpUSDC = 'LpUSDC', - // LpUSDT = 'LpUSDT', UniDAIWETH = 'UniDAIWETH', UniWBTCWETH = 'UniWBTCWETH', UniAAVEWETH = 'UniAAVEWETH', @@ -378,7 +368,7 @@ export interface iParamsPerNetwork { export interface iParamsPerPool { [AavePools.proto]: T; - [AavePools.lp]: T; + [AavePools.amm]: T; } export interface iBasicDistributionParams { @@ -460,7 +450,7 @@ export interface IAaveConfiguration extends ICommonConfiguration { ReservesConfig: iAavePoolAssets; } -export interface ILpConfiguration extends ICommonConfiguration { +export interface IAmmConfiguration extends ICommonConfiguration { ReservesConfig: iLpPoolAssets; } export interface ITokenAddress { diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index 36bf744b..642535d1 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -22,11 +22,6 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = { WBTC: oneEther.multipliedBy('47.332685').toFixed(), YFI: oneEther.multipliedBy('22.407436').toFixed(), ZRX: oneEther.multipliedBy('0.001151').toFixed(), - // LpDAI: oneEther.multipliedBy('0.00369068412860').toFixed(), - // LpUSDC: oneEther.multipliedBy('0.00367714136416').toFixed(), - // LpUSDT: oneEther.multipliedBy('0.00369068412860').toFixed(), - // LpWBTC: oneEther.multipliedBy('47.332685').toFixed(), - // LpWETH: oneEther.toFixed(), UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(), UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), diff --git a/markets/lp/commons.ts b/markets/amm/commons.ts similarity index 100% rename from markets/lp/commons.ts rename to markets/amm/commons.ts diff --git a/markets/lp/index.ts b/markets/amm/index.ts similarity index 96% rename from markets/lp/index.ts rename to markets/amm/index.ts index 5f66ce18..235db941 100644 --- a/markets/lp/index.ts +++ b/markets/amm/index.ts @@ -1,5 +1,5 @@ import { oneRay, ZERO_ADDRESS } from '../../helpers/constants'; -import { ILpConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; +import { IAmmConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types'; import { CommonsConfig } from './commons'; import { @@ -28,9 +28,9 @@ import { // POOL--SPECIFIC PARAMS // ---------------- -export const lpConfig: ILpConfiguration = { +export const AmmConfig: IAmmConfiguration = { ...CommonsConfig, - MarketId: 'Aave LP market', + MarketId: 'Aave AMM market', ProviderId: 2, ReservesConfig: { WETH: strategyWETH, @@ -129,4 +129,4 @@ export const lpConfig: ILpConfiguration = { }, }; -export default lpConfig; +export default AmmConfig; diff --git a/markets/lp/rateStrategies.ts b/markets/amm/rateStrategies.ts similarity index 94% rename from markets/lp/rateStrategies.ts rename to markets/amm/rateStrategies.ts index a91af2ea..26a68309 100644 --- a/markets/lp/rateStrategies.ts +++ b/markets/amm/rateStrategies.ts @@ -3,8 +3,8 @@ import { oneRay } from '../../helpers/constants'; import { IInterestRateStrategyParams } from '../../helpers/types'; // DAIWETH WBTCWETH AAVEWETH BATWETH USDCDAI CRVWETH LINKWETH MKRWETH RENWETH SNXWETH UNIWETH USDCWETH WBTCUSDC YFIWETH -export const rateStrategyLpBase: IInterestRateStrategyParams = { - name: "rateStrategyLpBase", +export const rateStrategyAmmBase: IInterestRateStrategyParams = { + name: "rateStrategyAmmBase", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), diff --git a/markets/lp/reservesConfigs.ts b/markets/amm/reservesConfigs.ts similarity index 92% rename from markets/lp/reservesConfigs.ts rename to markets/amm/reservesConfigs.ts index 21db2a1e..31b1a13c 100644 --- a/markets/lp/reservesConfigs.ts +++ b/markets/amm/reservesConfigs.ts @@ -1,6 +1,6 @@ import { eContractid, IReserveParams} from '../../helpers/types'; import { - rateStrategyLpBase, + rateStrategyAmmBase, rateStrategyStable, rateStrategyBaseOne, } from './rateStrategies'; @@ -67,7 +67,7 @@ export const strategyUSDT: IReserveParams = { }; export const strategyDAIWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -79,7 +79,7 @@ export const strategyDAIWETH: IReserveParams = { }; export const strategyWBTCWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -91,7 +91,7 @@ export const strategyWBTCWETH: IReserveParams = { }; export const strategyAAVEWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -103,7 +103,7 @@ export const strategyAAVEWETH: IReserveParams = { }; export const strategyBATWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -115,7 +115,7 @@ export const strategyBATWETH: IReserveParams = { }; export const strategyUSDCDAI: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -127,7 +127,7 @@ export const strategyUSDCDAI: IReserveParams = { }; export const strategyCRVWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '5000', liquidationThreshold: '6000', liquidationBonus: '11500', @@ -139,7 +139,7 @@ export const strategyCRVWETH: IReserveParams = { }; export const strategyLINKWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -151,7 +151,7 @@ export const strategyLINKWETH: IReserveParams = { }; export const strategyMKRWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -163,7 +163,7 @@ export const strategyMKRWETH: IReserveParams = { }; export const strategyRENWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -175,7 +175,7 @@ export const strategyRENWETH: IReserveParams = { }; export const strategySNXWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '4000', liquidationThreshold: '6000', liquidationBonus: '11500', @@ -187,7 +187,7 @@ export const strategySNXWETH: IReserveParams = { }; export const strategyUNIWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -199,7 +199,7 @@ export const strategyUNIWETH: IReserveParams = { }; export const strategyUSDCWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -211,7 +211,7 @@ export const strategyUSDCWETH: IReserveParams = { }; export const strategyWBTCUSDC: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -223,7 +223,7 @@ export const strategyWBTCUSDC: IReserveParams = { }; export const strategyYFIWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '5000', liquidationThreshold: '6000', liquidationBonus: '11500', diff --git a/package-lock.json b/package-lock.json index 129f12e4..2e0e9b42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,25338 +1,8 @@ { "name": "@aave/protocol-v2", "version": "1.0.1", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "@aave/protocol-v2", - "version": "1.0.1", - "license": "AGPLv3", - "dependencies": { - "tmp-promise": "^3.0.2" - }, - "devDependencies": { - "@nomiclabs/buidler": "^1.4.7", - "@nomiclabs/buidler-ethers": "2.0.0", - "@nomiclabs/buidler-etherscan": "^2.1.0", - "@nomiclabs/buidler-waffle": "2.0.0", - "@nomiclabs/hardhat-ethers": "^2.0.0", - "@nomiclabs/hardhat-waffle": "^2.0.0", - "@openzeppelin/contracts": "3.1.0", - "@tenderly/hardhat-tenderly": "^1.1.0-beta.3", - "@typechain/ethers-v4": "1.0.0", - "@typechain/ethers-v5": "^2.0.0", - "@typechain/truffle-v4": "2.0.2", - "@typechain/truffle-v5": "2.0.2", - "@typechain/web3-v1": "1.0.0", - "@types/chai": "4.2.11", - "@types/lowdb": "1.0.9", - "@types/mocha": "7.0.2", - "@types/node": "14.0.5", - "bignumber.js": "9.0.0", - "buidler-typechain": "0.1.1", - "chai": "4.2.0", - "chai-bignumber": "3.0.0", - "chai-bn": "^0.2.1", - "dotenv": "^8.2.0", - "eth-sig-util": "2.5.3", - "ethereum-waffle": "3.0.2", - "ethereumjs-util": "7.0.2", - "ethers": "^5.0.19", - "globby": "^11.0.1", - "hardhat": "^2.0.8", - "hardhat-gas-reporter": "^1.0.0", - "hardhat-typechain": "^0.3.3", - "husky": "^4.2.5", - "lowdb": "1.0.0", - "prettier": "^2.0.5", - "prettier-plugin-solidity": "^1.0.0-alpha.53", - "pretty-quick": "^2.0.1", - "solidity-coverage": "0.7.10", - "temp-hardhat-etherscan": "^2.0.2", - "ts-generator": "^0.1.1", - "ts-node": "^8.10.2", - "tslint": "^6.1.2", - "tslint-config-prettier": "^1.18.0", - "tslint-plugin-prettier": "^2.3.0", - "typechain": "^4.0.0", - "typescript": "^4.0.5" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "node_modules/@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "node_modules/@ensdomains/ens": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/@ensdomains/ens/-/ens-0.4.5.tgz", - "integrity": "sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw==", - "dev": true, - "dependencies": { - "bluebird": "^3.5.2", - "eth-ens-namehash": "^2.0.8", - "solc": "^0.4.20", - "testrpc": "0.0.1", - "web3-utils": "^1.0.0-beta.31" - } - }, - "node_modules/@ensdomains/ens/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/@ensdomains/ens/node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "node_modules/@ensdomains/ens/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@ensdomains/ens/node_modules/require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "node_modules/@ensdomains/ens/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/@ensdomains/ens/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@ensdomains/ens/node_modules/solc": { - "version": "0.4.26", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.26.tgz", - "integrity": "sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA==", - "dev": true, - "dependencies": { - "fs-extra": "^0.30.0", - "memorystream": "^0.3.1", - "require-from-string": "^1.1.0", - "semver": "^5.3.0", - "yargs": "^4.7.1" - }, - "bin": { - "solcjs": "solcjs" - } - }, - "node_modules/@ensdomains/ens/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "node_modules/@ensdomains/ens/node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "node_modules/@ensdomains/ens/node_modules/yargs": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", - "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true, - "dependencies": { - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "lodash.assign": "^4.0.3", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.1", - "which-module": "^1.0.0", - "window-size": "^0.2.0", - "y18n": "^3.2.1", - "yargs-parser": "^2.4.1" - } - }, - "node_modules/@ensdomains/ens/node_modules/yargs-parser": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "lodash.assign": "^4.0.6" - } - }, - "node_modules/@ensdomains/resolver": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@ensdomains/resolver/-/resolver-0.2.4.tgz", - "integrity": "sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA==", - "dev": true - }, - "node_modules/@ethereum-waffle/chai": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/chai/-/chai-3.2.0.tgz", - "integrity": "sha512-3mvI7luX8FSAX2yjklSN8rw8F8RNaMzZDadDkS9JvmoM4khByGe3mDn8rVroneBAcFusXJfL6BEssGj5S4mD7Q==", - "dev": true, - "dependencies": { - "@ethereum-waffle/provider": "^3.2.0", - "ethers": "^5.0.0" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/@ethereum-waffle/compiler": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/compiler/-/compiler-3.2.0.tgz", - "integrity": "sha512-Tg8YjbcVKQkNwhbiBf9Z4kKPolPO0IB+iYwAdpXNwgyMOH74guIHhFGtKOCPoY4VXR75erGgeQIt2PzIn/szCA==", - "dev": true, - "dependencies": { - "@resolver-engine/imports": "^0.3.3", - "@resolver-engine/imports-fs": "^0.3.3", - "@types/mkdirp": "^0.5.2", - "@types/node-fetch": "^2.5.5", - "ethers": "^5.0.1", - "mkdirp": "^0.5.1", - "node-fetch": "^2.6.0", - "solc": "^0.6.3" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/@ethereum-waffle/ens": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/ens/-/ens-3.2.0.tgz", - "integrity": "sha512-n4EYJDLAwN2X+2EsZMasXRlz5gYp39Tmy18RU4f6ZdnTNuVNw1BNkCC9VzrQooHGvHLjKZFPvcl+FRfBO+Xcyw==", - "dev": true, - "dependencies": { - "@ensdomains/ens": "^0.4.4", - "@ensdomains/resolver": "^0.2.4", - "ethers": "^5.0.1" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/@ethereum-waffle/mock-contract": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/mock-contract/-/mock-contract-3.2.0.tgz", - "integrity": "sha512-TfBt9ka2DXVxxIBee3WB0gSLgWCo9ZegqcdXjCz0QGlu+dEhL8W3+aLDYQoyx3kwlecfNl8EQ1V7g7GH8wrlMg==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.0.1", - "ethers": "^5.0.1" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/@ethereum-waffle/provider": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/provider/-/provider-3.2.0.tgz", - "integrity": "sha512-U9KyjMKIZuK4gi2kzWIJkAXYjtg0aIlEQ0F4yKqHMRyqAiSM6M4VJgn6tHisxe3Ev9z/jSnutKT8dyAEwlIYdw==", - "dev": true, - "dependencies": { - "@ethereum-waffle/ens": "^3.2.0", - "ethers": "^5.0.1", - "ganache-core": "^2.10.2", - "patch-package": "^6.2.2", - "postinstall-postinstall": "^2.1.0" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/@ethersproject/abi": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz", - "integrity": "sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==", - "dev": true, - "dependencies": { - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/strings": "^5.0.4" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.5.tgz", - "integrity": "sha512-i/CjElAkzV7vQBAeoz+IpjGfcFYEP9eD7j3fzZ0fzTq03DO7PPnR+xkEZ1IoDXGwDS+55aLM1xvLDwB/Lx6IOQ==", - "dev": true, - "dependencies": { - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/networks": "^5.0.3", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/transactions": "^5.0.5", - "@ethersproject/web": "^5.0.6" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.7.tgz", - "integrity": "sha512-8W8gy/QutEL60EoMEpvxZ8MFAEWs/JvH5nmZ6xeLXoZvmBCasGmxqHdYjo2cxg0nevkPkq9SeenSsBBZSCx+SQ==", - "dev": true, - "dependencies": { - "@ethersproject/abstract-provider": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.5.tgz", - "integrity": "sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA==", - "dev": true, - "dependencies": { - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/rlp": "^5.0.3", - "bn.js": "^4.4.0" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.4.tgz", - "integrity": "sha512-4KRykQ7BQMeOXfvio1YITwHjxwBzh92UoXIdzxDE1p53CK28bbHPdsPNYo0wl0El7lJAMpT2SOdL0hhbWRnyIA==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4" - } - }, - "node_modules/@ethersproject/basex": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.0.4.tgz", - "integrity": "sha512-ixIr/kKiAoSzOnSc777AGIOAhKai5Ivqr4HO/Gz+YG+xkfv6kqD6AW4ga9vM20Wwb0QBhh3LoRWTu4V1K+x9Ew==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/properties": "^5.0.3" - } - }, - "node_modules/@ethersproject/bignumber": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.8.tgz", - "integrity": "sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "bn.js": "^4.4.0" - } - }, - "node_modules/@ethersproject/bytes": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.5.tgz", - "integrity": "sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ==", - "dev": true, - "dependencies": { - "@ethersproject/logger": "^5.0.5" - } - }, - "node_modules/@ethersproject/constants": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.5.tgz", - "integrity": "sha512-foaQVmxp2+ik9FrLUCtVrLZCj4M3Ibgkqvh+Xw/vFRSerkjVSYePApaVE5essxhoSlF1U9oXfWY09QI2AXtgKA==", - "dev": true, - "dependencies": { - "@ethersproject/bignumber": "^5.0.7" - } - }, - "node_modules/@ethersproject/contracts": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.0.5.tgz", - "integrity": "sha512-tFI255lFbmbqMkgnuyhDWHl3yWqttPlReplYuVvDCT/SuvBjLR4ad2uipBlh1fh5X1ipK9ettAoV4S0HKim4Kw==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.0.5", - "@ethersproject/abstract-provider": "^5.0.4", - "@ethersproject/abstract-signer": "^5.0.4", - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3" - } - }, - "node_modules/@ethersproject/hash": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.6.tgz", - "integrity": "sha512-Gvh57v6BWhwnud6l7tMfQm32PRQ2DYx2WaAAQmAxAfYvmzUkpQCBstnGeNMXIL8/2wdkvcB2u+WZRWaZtsFuUQ==", - "dev": true, - "dependencies": { - "@ethersproject/abstract-signer": "^5.0.6", - "@ethersproject/address": "^5.0.5", - "@ethersproject/bignumber": "^5.0.8", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.4", - "@ethersproject/strings": "^5.0.4" - } - }, - "node_modules/@ethersproject/hdnode": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.0.5.tgz", - "integrity": "sha512-Ho4HZaK+KijE5adayvjAGusWMnT0mgwGa5hGMBofBOgX9nqiKf6Wxx68SXBGI1/L3rmKo6mlAjxUd8gefs0teQ==", - "dev": true, - "dependencies": { - "@ethersproject/abstract-signer": "^5.0.4", - "@ethersproject/basex": "^5.0.3", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/pbkdf2": "^5.0.3", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/sha2": "^5.0.3", - "@ethersproject/signing-key": "^5.0.4", - "@ethersproject/strings": "^5.0.4", - "@ethersproject/transactions": "^5.0.5", - "@ethersproject/wordlists": "^5.0.4" - } - }, - "node_modules/@ethersproject/json-wallets": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.0.7.tgz", - "integrity": "sha512-dgOn9JtGgjT28mDXs4LYY2rT4CzS6bG/rxoYuPq3TLHIf6nmvBcr33Fee6RrM/y8UAx4gyIkf6wb2cXsOctvQQ==", - "dev": true, - "dependencies": { - "@ethersproject/abstract-signer": "^5.0.4", - "@ethersproject/address": "^5.0.4", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/hdnode": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/pbkdf2": "^5.0.3", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/random": "^5.0.3", - "@ethersproject/strings": "^5.0.4", - "@ethersproject/transactions": "^5.0.5", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.4.tgz", - "integrity": "sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "js-sha3": "0.5.7" - } - }, - "node_modules/@ethersproject/keccak256/node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, - "node_modules/@ethersproject/logger": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.6.tgz", - "integrity": "sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ==", - "dev": true - }, - "node_modules/@ethersproject/networks": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.4.tgz", - "integrity": "sha512-/wHDTRms5mpJ09BoDrbNdFWINzONe05wZRgohCXvEv39rrH/Gd/yAnct8wC0RsW3tmFOgjgQxuBvypIxuUynTw==", - "dev": true, - "dependencies": { - "@ethersproject/logger": "^5.0.5" - } - }, - "node_modules/@ethersproject/pbkdf2": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.0.4.tgz", - "integrity": "sha512-9jVBjHXQKfr9+3bkCg01a8Cd1H9e+7Kw3ZMIvAxD0lZtuzrXsJxm1hVwY9KA+PRUvgS/9tTP4viXQYwLAax7zg==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/sha2": "^5.0.3" - } - }, - "node_modules/@ethersproject/properties": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.4.tgz", - "integrity": "sha512-UdyX3GqBxFt15B0uSESdDNmhvEbK3ACdDXl2soshoPcneXuTswHDeA0LoPlnaZzhbgk4p6jqb4GMms5C26Qu6A==", - "dev": true, - "dependencies": { - "@ethersproject/logger": "^5.0.5" - } - }, - "node_modules/@ethersproject/providers": { - "version": "5.0.14", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.0.14.tgz", - "integrity": "sha512-K9QRRkkHWyprm3g4L8U9aPx5uyivznL4RYemkN2shCQumyGqFJ5SO+OtQrgebVm0JpGwFAUGugnhRUh49sjErw==", - "dev": true, - "dependencies": { - "@ethersproject/abstract-provider": "^5.0.4", - "@ethersproject/abstract-signer": "^5.0.4", - "@ethersproject/address": "^5.0.4", - "@ethersproject/basex": "^5.0.3", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/networks": "^5.0.3", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/random": "^5.0.3", - "@ethersproject/rlp": "^5.0.3", - "@ethersproject/sha2": "^5.0.3", - "@ethersproject/strings": "^5.0.4", - "@ethersproject/transactions": "^5.0.5", - "@ethersproject/web": "^5.0.6", - "bech32": "1.1.4", - "ws": "7.2.3" - } - }, - "node_modules/@ethersproject/providers/node_modules/ws": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", - "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==", - "dev": true, - "engines": { - "node": ">=8.3.0" - } - }, - "node_modules/@ethersproject/random": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.0.4.tgz", - "integrity": "sha512-AIZJhqs6Ba4/+U3lOjt3QZbP6b/kuuGLJUYFUonAgWmkTHwqsCwYnFvnHKQSUuHbXHvErp7WFXFlztx+yMn3kQ==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5" - } - }, - "node_modules/@ethersproject/rlp": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.4.tgz", - "integrity": "sha512-5qrrZad7VTjofxSsm7Zg/7Dr4ZOln4S2CqiDdOuTv6MBKnXj0CiBojXyuDy52M8O3wxH0CyE924hXWTDV1PQWQ==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5" - } - }, - "node_modules/@ethersproject/sha2": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.0.4.tgz", - "integrity": "sha512-0yFhf1mspxAfWdXXoPtK94adUeu1R7/FzAa+DfEiZTc76sz/vHXf0LSIazoR3znYKFny6haBxME+usbvvEcF3A==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "hash.js": "1.1.3" - } - }, - "node_modules/@ethersproject/sha2/node_modules/hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/@ethersproject/signing-key": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.5.tgz", - "integrity": "sha512-Z1wY7JC1HVO4CvQWY2TyTTuAr8xK3bJijZw1a9G92JEmKdv1j255R/0YLBBcFTl2J65LUjtXynNJ2GbArPGi5g==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "elliptic": "6.5.3" - } - }, - "node_modules/@ethersproject/solidity": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.0.5.tgz", - "integrity": "sha512-DMFQ0ouXmNVoKWbGEUFGi8Urli4SJip9jXafQyFHWPRr5oJUqDVkNfwcyC37k+mhBG93k7qrYXCH2xJnGEOxHg==", - "dev": true, - "dependencies": { - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/sha2": "^5.0.3", - "@ethersproject/strings": "^5.0.4" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.5.tgz", - "integrity": "sha512-JED6WaIV00xM/gvj8vSnd+0VWtDYdidTmavFRCTQakqfz+4tDo6Jz5LHgG+dd45h7ah7ykCHW0C7ZXWEDROCXQ==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/logger": "^5.0.5" - } - }, - "node_modules/@ethersproject/transactions": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.6.tgz", - "integrity": "sha512-htsFhOD+NMBxx676A8ehSuwVV49iqpSB+CkjPZ02tpNew0K6p8g0CZ46Z1ZP946gIHAU80xQ0NACHYrjIUaCFA==", - "dev": true, - "dependencies": { - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/rlp": "^5.0.3", - "@ethersproject/signing-key": "^5.0.4" - } - }, - "node_modules/@ethersproject/units": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.0.6.tgz", - "integrity": "sha512-tsJuy4mipppdmooukRfhXt8fGx9nxvfvG6Xdy0RDm7LzHsjghjwQ69m2bCpId6SDSR1Uq1cQ9irPiUBSyWolUA==", - "dev": true, - "dependencies": { - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/logger": "^5.0.5" - } - }, - "node_modules/@ethersproject/wallet": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.0.7.tgz", - "integrity": "sha512-n2GX1+2Tc0qV8dguUcLkjNugINKvZY7u/5fEsn0skW9rz5+jHTR5IKMV6jSfXA+WjQT8UCNMvkI3CNcdhaPbTQ==", - "dev": true, - "dependencies": { - "@ethersproject/abstract-provider": "^5.0.4", - "@ethersproject/abstract-signer": "^5.0.4", - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/hdnode": "^5.0.4", - "@ethersproject/json-wallets": "^5.0.6", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/random": "^5.0.3", - "@ethersproject/signing-key": "^5.0.4", - "@ethersproject/transactions": "^5.0.5", - "@ethersproject/wordlists": "^5.0.4" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.9.tgz", - "integrity": "sha512-//QNlv1MSkOII1hv3+HQwWoiVFS+BMVGI0KYeUww4cyrEktnx1QIez5bTSab9s9fWTFaWKNmQNBwMbxAqPuYDw==", - "dev": true, - "dependencies": { - "@ethersproject/base64": "^5.0.3", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/strings": "^5.0.4" - } - }, - "node_modules/@ethersproject/wordlists": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.0.5.tgz", - "integrity": "sha512-XA3ycFltVrCTQt04w5nHu3Xq5Z6HjqWsXaAYQHFdqtugyUsIumaO9S5MOwFFuUYTNkZUoT3jCRa/OBS+K4tLfA==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/strings": "^5.0.4" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", - "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.3", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", - "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.3", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nomiclabs/buidler": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/@nomiclabs/buidler/-/buidler-1.4.8.tgz", - "integrity": "sha512-OUnNWx+WXOJzueJCfyuEXu3qNMq1j9eGDDpgflpRwjPeiQQnvVzfbwrPjs0PlxOC3Xtmaxabtgek5wGxS1C7Ew==", - "dev": true, - "dependencies": { - "@nomiclabs/ethereumjs-vm": "^4.1.1", - "@sentry/node": "^5.18.1", - "@solidity-parser/parser": "^0.5.2", - "@types/bn.js": "^4.11.5", - "@types/lru-cache": "^5.1.0", - "abort-controller": "^3.0.0", - "ansi-escapes": "^4.3.0", - "chalk": "^2.4.2", - "chokidar": "^3.4.0", - "ci-info": "^2.0.0", - "debug": "^4.1.1", - "deepmerge": "^2.1.0", - "download": "^7.1.0", - "enquirer": "^2.3.0", - "env-paths": "^2.2.0", - "eth-sig-util": "^2.5.2", - "ethereum-cryptography": "^0.1.2", - "ethereumjs-abi": "^0.6.8", - "ethereumjs-account": "^3.0.0", - "ethereumjs-block": "^2.2.0", - "ethereumjs-common": "^1.3.2", - "ethereumjs-tx": "^2.1.1", - "ethereumjs-util": "^6.1.0", - "find-up": "^2.1.0", - "fp-ts": "1.19.3", - "fs-extra": "^7.0.1", - "glob": "^7.1.3", - "io-ts": "1.10.4", - "is-installed-globally": "^0.2.0", - "lodash": "^4.17.11", - "merkle-patricia-tree": "^3.0.0", - "mocha": "^7.1.2", - "node-fetch": "^2.6.0", - "qs": "^6.7.0", - "raw-body": "^2.4.1", - "semver": "^6.3.0", - "slash": "^3.0.0", - "solc": "0.6.8", - "source-map-support": "^0.5.13", - "ts-essentials": "^2.0.7", - "tsort": "0.0.1", - "uuid": "^3.3.2", - "ws": "^7.2.1" - }, - "bin": { - "buidler": "internal/cli/cli.js", - "builder": "internal/cli/cli-with-a-typo.js" - }, - "engines": { - "node": ">=8.2.0" - } - }, - "node_modules/@nomiclabs/buidler-ethers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nomiclabs/buidler-ethers/-/buidler-ethers-2.0.0.tgz", - "integrity": "sha512-Lf5XLClEeWYo6jVrGAqGBAcKTOP6IAChAR4qcDS36BkQnWakoRKcoSbwhr2YmTNTRAvgDWTmjQYbV17udJ+Alw==", - "dev": true - }, - "node_modules/@nomiclabs/buidler-etherscan": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@nomiclabs/buidler-etherscan/-/buidler-etherscan-2.1.0.tgz", - "integrity": "sha512-Rh1PGCtIVNU9zDSnLn6WlJDMBM9LXzkwNnzRFnTrMdA+Aa9nMVX7qwbAXG9pyIIsuqNH6MRfk7CDvi8aMoojng==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.0.2", - "@ethersproject/address": "^5.0.2", - "cbor": "^5.0.2", - "ethereumjs-abi": "^0.6.8", - "node-fetch": "^2.6.0", - "semver": "^6.3.0" - } - }, - "node_modules/@nomiclabs/buidler-waffle": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nomiclabs/buidler-waffle/-/buidler-waffle-2.0.0.tgz", - "integrity": "sha512-slGUjMmooIFehk1EMz+gSD07x6RVhp9aEHCmjk5MDm9FuV0+1IhPrk0DDl9ZKYlb5dgTRSWOqzIOXLXhnjmt0A==", - "dev": true, - "dependencies": { - "@types/sinon-chai": "^3.2.3", - "@types/web3": "1.0.19" - } - }, - "node_modules/@nomiclabs/buidler/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/@nomiclabs/ethereumjs-vm": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@nomiclabs/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz", - "integrity": "sha512-+XwqoO941bILTO4KDLIUJ37U42ySxw6it7jyoi0tKv0/VUcOrWKF1TCQWMv6dBDRlxpPQd273n9o5SVlYYLRWQ==", - "dev": true, - "dependencies": { - "async": "^2.1.2", - "async-eventemitter": "^0.2.2", - "core-js-pure": "^3.0.1", - "ethereumjs-account": "^3.0.0", - "ethereumjs-block": "^2.2.2", - "ethereumjs-blockchain": "^4.0.3", - "ethereumjs-common": "^1.5.0", - "ethereumjs-tx": "^2.1.2", - "ethereumjs-util": "^6.2.0", - "fake-merkle-patricia-tree": "^1.0.1", - "functional-red-black-tree": "^1.0.1", - "merkle-patricia-tree": "^2.3.2", - "rustbn.js": "~0.2.0", - "safe-buffer": "^5.1.1", - "util.promisify": "^1.0.0" - } - }, - "node_modules/@nomiclabs/ethereumjs-vm/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/@nomiclabs/ethereumjs-vm/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/@nomiclabs/ethereumjs-vm/node_modules/merkle-patricia-tree": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", - "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", - "dev": true, - "dependencies": { - "async": "^1.4.2", - "ethereumjs-util": "^5.0.0", - "level-ws": "0.0.0", - "levelup": "^1.2.1", - "memdown": "^1.0.0", - "readable-stream": "^2.0.0", - "rlp": "^2.0.0", - "semaphore": ">=1.0.1" - } - }, - "node_modules/@nomiclabs/ethereumjs-vm/node_modules/merkle-patricia-tree/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/@nomiclabs/ethereumjs-vm/node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/@nomiclabs/ethereumjs-vm/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/@nomiclabs/ethereumjs-vm/node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/@nomiclabs/ethereumjs-vm/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/@nomiclabs/ethereumjs-vm/node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/@nomiclabs/hardhat-ethers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.0.tgz", - "integrity": "sha512-fIi6XP9PgKqwSNVcLDr6S5hvGlc21PendaLD5eGdXEXc9aYQ0OJX8Mk3evs+p78x7W9n9U3ZcKtTiGc1+YScDw==", - "dev": true - }, - "node_modules/@nomiclabs/hardhat-waffle": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.0.tgz", - "integrity": "sha512-CnG9JC0rgqa68LTgyETxBUEWYAovvNGVs5abqaXjG80eF7iMLjDjM8IjOM87siAaxaxFCf6VBMJmtueqVq7jZw==", - "dev": true, - "dependencies": { - "@types/sinon-chai": "^3.2.3", - "@types/web3": "1.0.19" - } - }, - "node_modules/@openzeppelin/contracts": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-3.1.0.tgz", - "integrity": "sha512-dVXDnUKxrAKLzPdCRkz+N8qsVkK1XxJ6kk3zuI6zaQmcKxN7CkizoDP7lXxcs/Mi2I0mxceTRjJBqlzFffLJrQ==", - "dev": true - }, - "node_modules/@resolver-engine/core": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz", - "integrity": "sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ==", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "is-url": "^1.2.4", - "request": "^2.85.0" - } - }, - "node_modules/@resolver-engine/core/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/@resolver-engine/fs": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@resolver-engine/fs/-/fs-0.3.3.tgz", - "integrity": "sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ==", - "dev": true, - "dependencies": { - "@resolver-engine/core": "^0.3.3", - "debug": "^3.1.0" - } - }, - "node_modules/@resolver-engine/fs/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/@resolver-engine/imports": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@resolver-engine/imports/-/imports-0.3.3.tgz", - "integrity": "sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q==", - "dev": true, - "dependencies": { - "@resolver-engine/core": "^0.3.3", - "debug": "^3.1.0", - "hosted-git-info": "^2.6.0", - "path-browserify": "^1.0.0", - "url": "^0.11.0" - } - }, - "node_modules/@resolver-engine/imports-fs": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz", - "integrity": "sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA==", - "dev": true, - "dependencies": { - "@resolver-engine/fs": "^0.3.3", - "@resolver-engine/imports": "^0.3.3", - "debug": "^3.1.0" - } - }, - "node_modules/@resolver-engine/imports-fs/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/@resolver-engine/imports/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/@sentry/core": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.27.4.tgz", - "integrity": "sha512-IbI37cIZU/qBQouuUXaLbGF/9xYFp5STqmj1Gv64l0IZe4JnEp06V3yD5GxQ/mJ78vSfOqfwLooVCUw9FA61sQ==", - "dev": true, - "dependencies": { - "@sentry/hub": "5.27.4", - "@sentry/minimal": "5.27.4", - "@sentry/types": "5.27.4", - "@sentry/utils": "5.27.4", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/hub": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.27.4.tgz", - "integrity": "sha512-Ba1AqcjvSd2S+fpdXtXCrVXdrzq9E2Etb2eHUOkEYwSsq7StMOw7E8YHDPAo+to8zUbpMPz/Z9XGhFkyAbImGQ==", - "dev": true, - "dependencies": { - "@sentry/types": "5.27.4", - "@sentry/utils": "5.27.4", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/minimal": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.27.4.tgz", - "integrity": "sha512-biw5YfIQwvDoaRhLarfeRQ6MJ9UJOoDTmu8Kgg18prJy4rtfDowNJP0OBs5XAsTk6SWAXiE3g7vqUJBXgs7BWA==", - "dev": true, - "dependencies": { - "@sentry/hub": "5.27.4", - "@sentry/types": "5.27.4", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/node": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.27.4.tgz", - "integrity": "sha512-fv3FfQ6FiNV56LKk6t48oNw8qgf7X5fEhqhvKAoU7w+BL9AhChzh9v7sWn9ppDtRFE45tFfsZh0J/8ox5jpnfQ==", - "dev": true, - "dependencies": { - "@sentry/core": "5.27.4", - "@sentry/hub": "5.27.4", - "@sentry/tracing": "5.27.4", - "@sentry/types": "5.27.4", - "@sentry/utils": "5.27.4", - "cookie": "^0.4.1", - "https-proxy-agent": "^5.0.0", - "lru_map": "^0.3.3", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/tracing": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.27.4.tgz", - "integrity": "sha512-f3nG8ozCdcbFOzsnBCZ8w+/WfoNiAd0Ctr643L0rsFbaSzPWxbPMe3LNVrWwFVo6mHacG3/2HYmJ3CYMiWyTKQ==", - "dev": true, - "dependencies": { - "@sentry/hub": "5.27.4", - "@sentry/minimal": "5.27.4", - "@sentry/types": "5.27.4", - "@sentry/utils": "5.27.4", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/types": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.27.4.tgz", - "integrity": "sha512-41h3c7tgtSS8UBmfvEckSr+7V7/IVOjt/EiydyOd6s0N18zSFfGY5HdA6g+eFtIJK3DhWkUHCHZNanD5IY5YCQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/utils": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.27.4.tgz", - "integrity": "sha512-shV1I/q+Tob3hUxRj11DfMhe9PNDiv85hUUoRloZGGwu275dMwpswb2uwgSmjc2Ao4pnMKVx8TL1hC3kGLVHTQ==", - "dev": true, - "dependencies": { - "@sentry/types": "5.27.4", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sindresorhus/is": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@solidity-parser/parser": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.5.2.tgz", - "integrity": "sha512-uRyvnvVYmgNmTBpWDbBsH/0kPESQhQpEc4KsvMRLVzFJ1o1s0uIv0Y6Y9IB5vI1Dwz2CbS4X/y4Wyw/75cTFnQ==", - "dev": true - }, - "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@tenderly/hardhat-tenderly": { - "version": "1.1.0-beta.3", - "resolved": "https://registry.npmjs.org/@tenderly/hardhat-tenderly/-/hardhat-tenderly-1.1.0-beta.3.tgz", - "integrity": "sha512-CCiS3bBCc4MhOTI5oHRAuVy/Xan6/8oNnjiwbsRvG1hdUis+EL/UVwn5yrUM1qXQTPz/La3TvRkfEa/pq1gimw==", - "dev": true, - "dependencies": { - "axios": "^0.20.0", - "fs-extra": "^9.0.1", - "js-yaml": "^3.14.0" - } - }, - "node_modules/@tenderly/hardhat-tenderly/node_modules/fs-extra": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", - "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@tenderly/hardhat-tenderly/node_modules/js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@tenderly/hardhat-tenderly/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "node_modules/@tenderly/hardhat-tenderly/node_modules/jsonfile/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@tenderly/hardhat-tenderly/node_modules/universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@truffle/error": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@truffle/error/-/error-0.0.7.tgz", - "integrity": "sha512-UIfVKsXSXocKnn5+RNklUXNoGd/JVj7V8KmC48TQzmjU33HQI86PX0JDS7SpHMHasI3w9X//1q7Lu7nZtj3Zzg==", - "dev": true - }, - "node_modules/@truffle/interface-adapter": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.3.3.tgz", - "integrity": "sha512-l3I4WFTfnBSIfG96IOBRtAIE6AHDAxcOUJE7W5zh9hocQwzQlGWc2yEyyTcLa0656TTM8RxaZZ2S/KdHHMvCaw==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.8", - "ethers": "^4.0.32", - "lodash": "^4.17.13", - "web3": "1.2.2" - } - }, - "node_modules/@truffle/interface-adapter/node_modules/@types/node": { - "version": "12.19.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", - "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", - "dev": true - }, - "node_modules/@truffle/interface-adapter/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/@truffle/interface-adapter/node_modules/ethers": { - "version": "4.0.48", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.48.tgz", - "integrity": "sha512-sZD5K8H28dOrcidzx9f8KYh8083n5BexIO3+SbE4jK83L85FxtpXZBCQdXb8gkg+7sBqomcLhhkU7UHL+F7I2g==", - "dev": true, - "dependencies": { - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "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" - } - }, - "node_modules/@truffle/interface-adapter/node_modules/hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/@truffle/interface-adapter/node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, - "node_modules/@truffle/interface-adapter/node_modules/scrypt-js": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", - "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", - "dev": true - }, - "node_modules/@truffle/interface-adapter/node_modules/setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", - "dev": true - }, - "node_modules/@truffle/interface-adapter/node_modules/uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", - "dev": true - }, - "node_modules/@truffle/interface-adapter/node_modules/web3": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.2.tgz", - "integrity": "sha512-/ChbmB6qZpfGx6eNpczt5YSUBHEA5V2+iUCbn85EVb3Zv6FVxrOo5Tv7Lw0gE2tW7EEjASbCyp3mZeiZaCCngg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@types/node": "^12.6.1", - "web3-bzz": "1.2.2", - "web3-core": "1.2.2", - "web3-eth": "1.2.2", - "web3-eth-personal": "1.2.2", - "web3-net": "1.2.2", - "web3-shh": "1.2.2", - "web3-utils": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/interface-adapter/node_modules/web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/interface-adapter/node_modules/web3-utils/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/@truffle/provider": { - "version": "0.1.19", - "resolved": "https://registry.npmjs.org/@truffle/provider/-/provider-0.1.19.tgz", - "integrity": "sha512-ke8iQmzW4Y99+8iff8xQcc+mCNU4AkwtaZ/iSpmVD8qpLytw8/DSNCm0RiEz9/+I93Q1zqI4Jnij/rXnkS2Njw==", - "dev": true, - "dependencies": { - "@truffle/error": "^0.0.7", - "@truffle/interface-adapter": "^0.3.0", - "web3": "1.2.1" - } - }, - "node_modules/@truffle/provider/node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@truffle/provider/node_modules/@types/node": { - "version": "10.17.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", - "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", - "dev": true - }, - "node_modules/@truffle/provider/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/@truffle/provider/node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@truffle/provider/node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@truffle/provider/node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@truffle/provider/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/@truffle/provider/node_modules/ethers": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", - "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", - "dev": true, - "dependencies": { - "@types/node": "^10.3.2", - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "elliptic": "6.3.3", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.3", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - } - }, - "node_modules/@truffle/provider/node_modules/ethers/node_modules/elliptic": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", - "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", - "dev": true, - "dependencies": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/@truffle/provider/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@truffle/provider/node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/@truffle/provider/node_modules/hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "node_modules/@truffle/provider/node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, - "node_modules/@truffle/provider/node_modules/normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@truffle/provider/node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@truffle/provider/node_modules/scrypt-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", - "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", - "dev": true - }, - "node_modules/@truffle/provider/node_modules/semver": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz", - "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@truffle/provider/node_modules/setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", - "dev": true - }, - "node_modules/@truffle/provider/node_modules/uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", - "dev": true - }, - "node_modules/@truffle/provider/node_modules/web3": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.1.tgz", - "integrity": "sha512-nNMzeCK0agb5i/oTWNdQ1aGtwYfXzHottFP2Dz0oGIzavPMGSKyVlr8ibVb1yK5sJBjrWVnTdGaOC2zKDFuFRw==", - "dev": true, - "dependencies": { - "web3-bzz": "1.2.1", - "web3-core": "1.2.1", - "web3-eth": "1.2.1", - "web3-eth-personal": "1.2.1", - "web3-net": "1.2.1", - "web3-shh": "1.2.1", - "web3-utils": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-bzz": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.1.tgz", - "integrity": "sha512-LdOO44TuYbGIPfL4ilkuS89GQovxUpmLz6C1UC7VYVVRILeZS740FVB3j9V4P4FHUk1RenaDfKhcntqgVCHtjw==", - "dev": true, - "dependencies": { - "got": "9.6.0", - "swarm-js": "0.1.39", - "underscore": "1.9.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-core": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.1.tgz", - "integrity": "sha512-5ODwIqgl8oIg/0+Ai4jsLxkKFWJYE0uLuE1yUKHNVCL4zL6n3rFjRMpKPokd6id6nJCNgeA64KdWQ4XfpnjdMg==", - "dev": true, - "dependencies": { - "web3-core-helpers": "1.2.1", - "web3-core-method": "1.2.1", - "web3-core-requestmanager": "1.2.1", - "web3-utils": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-core-helpers": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.1.tgz", - "integrity": "sha512-Gx3sTEajD5r96bJgfuW377PZVFmXIH4TdqDhgGwd2lZQCcMi+DA4TgxJNJGxn0R3aUVzyyE76j4LBrh412mXrw==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-eth-iban": "1.2.1", - "web3-utils": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-core-method": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.1.tgz", - "integrity": "sha512-Ghg2WS23qi6Xj8Od3VCzaImLHseEA7/usvnOItluiIc5cKs00WYWsNy2YRStzU9a2+z8lwQywPYp0nTzR/QXdQ==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.1", - "web3-core-promievent": "1.2.1", - "web3-core-subscriptions": "1.2.1", - "web3-utils": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-core-promievent": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.1.tgz", - "integrity": "sha512-IVUqgpIKoeOYblwpex4Hye6npM0aMR+kU49VP06secPeN0rHMyhGF0ZGveWBrGvf8WDPI7jhqPBFIC6Jf3Q3zw==", - "dev": true, - "dependencies": { - "any-promise": "1.3.0", - "eventemitter3": "3.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-core-requestmanager": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.1.tgz", - "integrity": "sha512-xfknTC69RfYmLKC+83Jz73IC3/sS2ZLhGtX33D4Q5nQ8yc39ElyAolxr9sJQS8kihOcM6u4J+8gyGMqsLcpIBg==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.1", - "web3-providers-http": "1.2.1", - "web3-providers-ipc": "1.2.1", - "web3-providers-ws": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-core-subscriptions": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.1.tgz", - "integrity": "sha512-nmOwe3NsB8V8UFsY1r+sW6KjdOS68h8nuh7NzlWxBQT/19QSUGiERRTaZXWu5BYvo1EoZRMxCKyCQpSSXLc08g==", - "dev": true, - "dependencies": { - "eventemitter3": "3.1.2", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-eth": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.1.tgz", - "integrity": "sha512-/2xly4Yry5FW1i+uygPjhfvgUP/MS/Dk+PDqmzp5M88tS86A+j8BzKc23GrlA8sgGs0645cpZK/999LpEF5UdA==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core": "1.2.1", - "web3-core-helpers": "1.2.1", - "web3-core-method": "1.2.1", - "web3-core-subscriptions": "1.2.1", - "web3-eth-abi": "1.2.1", - "web3-eth-accounts": "1.2.1", - "web3-eth-contract": "1.2.1", - "web3-eth-ens": "1.2.1", - "web3-eth-iban": "1.2.1", - "web3-eth-personal": "1.2.1", - "web3-net": "1.2.1", - "web3-utils": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-eth-abi": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.1.tgz", - "integrity": "sha512-jI/KhU2a/DQPZXHjo2GW0myEljzfiKOn+h1qxK1+Y9OQfTcBMxrQJyH5AP89O6l6NZ1QvNdq99ThAxBFoy5L+g==", - "dev": true, - "dependencies": { - "ethers": "4.0.0-beta.3", - "underscore": "1.9.1", - "web3-utils": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-eth-accounts": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.1.tgz", - "integrity": "sha512-26I4qq42STQ8IeKUyur3MdQ1NzrzCqPsmzqpux0j6X/XBD7EjZ+Cs0lhGNkSKH5dI3V8CJasnQ5T1mNKeWB7nQ==", - "dev": true, - "dependencies": { - "any-promise": "1.3.0", - "crypto-browserify": "3.12.0", - "eth-lib": "0.2.7", - "scryptsy": "2.1.0", - "semver": "6.2.0", - "underscore": "1.9.1", - "uuid": "3.3.2", - "web3-core": "1.2.1", - "web3-core-helpers": "1.2.1", - "web3-core-method": "1.2.1", - "web3-utils": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-eth-accounts/node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/@truffle/provider/node_modules/web3-eth-contract": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.1.tgz", - "integrity": "sha512-kYFESbQ3boC9bl2rYVghj7O8UKMiuKaiMkxvRH5cEDHil8V7MGEGZNH0slSdoyeftZVlaWSMqkRP/chfnKND0g==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core": "1.2.1", - "web3-core-helpers": "1.2.1", - "web3-core-method": "1.2.1", - "web3-core-promievent": "1.2.1", - "web3-core-subscriptions": "1.2.1", - "web3-eth-abi": "1.2.1", - "web3-utils": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-eth-ens": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.1.tgz", - "integrity": "sha512-lhP1kFhqZr2nnbu3CGIFFrAnNxk2veXpOXBY48Tub37RtobDyHijHgrj+xTh+mFiPokyrapVjpFsbGa+Xzye4Q==", - "dev": true, - "dependencies": { - "eth-ens-namehash": "2.0.8", - "underscore": "1.9.1", - "web3-core": "1.2.1", - "web3-core-helpers": "1.2.1", - "web3-core-promievent": "1.2.1", - "web3-eth-abi": "1.2.1", - "web3-eth-contract": "1.2.1", - "web3-utils": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-eth-iban": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.1.tgz", - "integrity": "sha512-9gkr4QPl1jCU+wkgmZ8EwODVO3ovVj6d6JKMos52ggdT2YCmlfvFVF6wlGLwi0VvNa/p+0BjJzaqxnnG/JewjQ==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "web3-utils": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-eth-personal": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.1.tgz", - "integrity": "sha512-RNDVSiaSoY4aIp8+Hc7z+X72H7lMb3fmAChuSBADoEc7DsJrY/d0R5qQDK9g9t2BO8oxgLrLNyBP/9ub2Hc6Bg==", - "dev": true, - "dependencies": { - "web3-core": "1.2.1", - "web3-core-helpers": "1.2.1", - "web3-core-method": "1.2.1", - "web3-net": "1.2.1", - "web3-utils": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-net": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.1.tgz", - "integrity": "sha512-Yt1Bs7WgnLESPe0rri/ZoPWzSy55ovioaP35w1KZydrNtQ5Yq4WcrAdhBzcOW7vAkIwrsLQsvA+hrOCy7mNauw==", - "dev": true, - "dependencies": { - "web3-core": "1.2.1", - "web3-core-method": "1.2.1", - "web3-utils": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-providers-http": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.1.tgz", - "integrity": "sha512-BDtVUVolT9b3CAzeGVA/np1hhn7RPUZ6YYGB/sYky+GjeO311Yoq8SRDUSezU92x8yImSC2B+SMReGhd1zL+bQ==", - "dev": true, - "dependencies": { - "web3-core-helpers": "1.2.1", - "xhr2-cookies": "1.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-providers-ipc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.1.tgz", - "integrity": "sha512-oPEuOCwxVx8L4CPD0TUdnlOUZwGBSRKScCz/Ws2YHdr9Ium+whm+0NLmOZjkjQp5wovQbyBzNa6zJz1noFRvFA==", - "dev": true, - "dependencies": { - "oboe": "2.1.4", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-providers-ws": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.1.tgz", - "integrity": "sha512-oqsQXzu+ejJACVHy864WwIyw+oB21nw/pI65/sD95Zi98+/HQzFfNcIFneF1NC4bVF3VNX4YHTNq2I2o97LAiA==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.1", - "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-shh": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.1.tgz", - "integrity": "sha512-/3Cl04nza5kuFn25bV3FJWa0s3Vafr5BlT933h26xovQ6HIIz61LmvNQlvX1AhFL+SNJOTcQmK1SM59vcyC8bA==", - "dev": true, - "dependencies": { - "web3-core": "1.2.1", - "web3-core-method": "1.2.1", - "web3-core-subscriptions": "1.2.1", - "web3-net": "1.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/provider/node_modules/web3-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.1.tgz", - "integrity": "sha512-Mrcn3l58L+yCKz3zBryM6JZpNruWuT0OCbag8w+reeNROSGVlXzUQkU+gtAwc9JCZ7tKUyg67+2YUGqUjVcyBA==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@typechain/ethers-v4": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v4/-/ethers-v4-1.0.0.tgz", - "integrity": "sha512-tN9XV0ezbLaEuK6jC5gW6AiH4ihq9lMl1ifJr700oBjknKKNDO6jUSzUE56gJzhW/fuyGsb4zsCHwf3JCkBd9w==", - "dev": true - }, - "node_modules/@typechain/ethers-v5": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz", - "integrity": "sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw==", - "dev": true, - "dependencies": { - "ethers": "^5.0.2" - } - }, - "node_modules/@typechain/truffle-v4": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@typechain/truffle-v4/-/truffle-v4-2.0.2.tgz", - "integrity": "sha512-YoJAzgQZeark7lwInLnJ3u14JO980W5mVzFUkZny40+/WSPlox5Sa5IWLkULrgwkEWoiLA2sTpJ2tE7nCtSC2Q==", - "dev": true - }, - "node_modules/@typechain/truffle-v5": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@typechain/truffle-v5/-/truffle-v5-2.0.2.tgz", - "integrity": "sha512-g4N2kfol1S3g/QUkmpzukCGZiKWUdXsSms1be/+W4+R0DPMz1Q/76tY+C6bD7G/KeLhkiDKcnZFmNVNcAgjIfQ==", - "dev": true - }, - "node_modules/@typechain/web3-v1": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@typechain/web3-v1/-/web3-v1-1.0.0.tgz", - "integrity": "sha512-MM8PmsblePaxy5BCYEuPtR4ajigPf504VRQzZgFYqs6KuFnJxbOjF8jNYT12P6UvUX7us75Wc78QdbvOHbb4hA==", - "dev": true - }, - "node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/chai": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.11.tgz", - "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", - "dev": true - }, - "node_modules/@types/concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-OU2+C7X+5Gs42JZzXoto7yOQ0A0=", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/form-data": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", - "integrity": "sha1-yayFsqX9GENbjIXZ7LUObWyJP/g=", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/lodash": { - "version": "4.14.165", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.165.tgz", - "integrity": "sha512-tjSSOTHhI5mCHTy/OOXYIhi2Wt1qcbHmuXD1Ha7q70CgI/I71afO4XtLb/cVexki1oVYchpul/TOuu3Arcdxrg==", - "dev": true - }, - "node_modules/@types/lowdb": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/lowdb/-/lowdb-1.0.9.tgz", - "integrity": "sha512-LBRG5EPXFOJDoJc9jACstMhtMP+u+UkPYllBeGQXXKiaHc+uzJs9+/Aynb/5KkX33DtrIiKyzNVTPQc/4RcD6A==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/lru-cache": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.0.tgz", - "integrity": "sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w==", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "node_modules/@types/mkdirp": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz", - "integrity": "sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", - "dev": true - }, - "node_modules/@types/node": { - "version": "14.0.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.5.tgz", - "integrity": "sha512-90hiq6/VqtQgX8Sp0EzeIsv3r+ellbGj4URKj5j30tLlZvRUpnAe9YbYnjl3pJM93GyXU0tghHhvXHq+5rnCKA==", - "dev": true - }, - "node_modules/@types/node-fetch": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", - "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "form-data": "^3.0.0" - } - }, - "node_modules/@types/node-fetch/node_modules/form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "node_modules/@types/pbkdf2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", - "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/prettier": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.5.tgz", - "integrity": "sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ==", - "dev": true - }, - "node_modules/@types/qs": { - "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 - }, - "node_modules/@types/resolve": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", - "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/secp256k1": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", - "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/sinon": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.8.tgz", - "integrity": "sha512-IVnI820FZFMGI+u1R+2VdRaD/82YIQTdqLYC9DLPszZuynAJDtCvCtCs3bmyL66s7FqRM3+LPX7DhHnVTaagDw==", - "dev": true, - "dependencies": { - "@types/sinonjs__fake-timers": "*" - } - }, - "node_modules/@types/sinon-chai": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.5.tgz", - "integrity": "sha512-bKQqIpew7mmIGNRlxW6Zli/QVyc3zikpGzCa797B/tRnD9OtHvZ/ts8sYXV+Ilj9u3QRaUEM8xrjgd1gwm1BpQ==", - "dev": true, - "dependencies": { - "@types/chai": "*", - "@types/sinon": "*" - } - }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", - "integrity": "sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==", - "dev": true - }, - "node_modules/@types/underscore": { - "version": "1.10.24", - "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.10.24.tgz", - "integrity": "sha512-T3NQD8hXNW2sRsSbLNjF/aBo18MyJlbw0lSpQHB/eZZtScPdexN4HSa8cByYwTw9Wy7KuOFr81mlDQcQQaZ79w==", - "dev": true - }, - "node_modules/@types/web3": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/@types/web3/-/web3-1.0.19.tgz", - "integrity": "sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A==", - "dev": true, - "dependencies": { - "@types/bn.js": "*", - "@types/underscore": "*" - } - }, - "node_modules/@web3-js/scrypt-shim": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz", - "integrity": "sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "scryptsy": "^2.1.0", - "semver": "^6.3.0" - } - }, - "node_modules/@web3-js/websocket": { - "version": "1.0.30", - "resolved": "https://registry.npmjs.org/@web3-js/websocket/-/websocket-1.0.30.tgz", - "integrity": "sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "nan": "^2.14.0", - "typedarray-to-buffer": "^3.1.5", - "yaeti": "^0.0.6" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@web3-js/websocket/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@web3-js/websocket/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "node_modules/abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/abstract-leveldown": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", - "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/abstract-leveldown/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/address": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", - "dev": true, - "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/adm-zip": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", - "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", - "dev": true, - "engines": { - "node": ">=0.3.0" - } - }, - "node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=", - "dev": true - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.4.2" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "dev": true, - "dependencies": { - "type-fest": "^0.11.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/antlr4": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.8.0.tgz", - "integrity": "sha512-en/MxQ4OkPgGJQ3wD/muzj1uDnFSzdFIhc2+c6bHZokWkuBb6RRvFjpWhPxWLbgQvaEzldJZ0GSQpfSAaE3hqg==", - "dev": true - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", - "dev": true - }, - "node_modules/anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/archive-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", - "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", - "dev": true, - "dependencies": { - "file-type": "^4.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/archive-type/node_modules/file-type": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", - "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/array-differ": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", - "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true - }, - "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/async-eventemitter": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", - "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", - "dev": true, - "dependencies": { - "async": "^2.4.0" - } - }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, - "node_modules/axios": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz", - "integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.10.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base-x": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", - "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "dev": true - }, - "node_modules/bignumber.js": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", - "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/bl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", - "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", - "dev": true, - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/bl/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/bl/node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/bl/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/bl/node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/blakejs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", - "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=", - "dev": true - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - }, - "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/body-parser/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/body-parser/node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "node_modules/browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "dev": true, - "dependencies": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "node_modules/browserify-rsa/node_modules/bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true - }, - "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "node_modules/browserify-sign/node_modules/bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", - "dev": true, - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dev": true, - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "dependencies": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "node_modules/buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true - }, - "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "node_modules/buffer-to-arraybuffer": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=", - "dev": true - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "node_modules/buidler-typechain": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buidler-typechain/-/buidler-typechain-0.1.1.tgz", - "integrity": "sha512-UXS6m0MUzomDWFfd6Jivbz/wmNZo4dpW/Qa6Lq89qhS/qms/j1haJqlMxsDu+tCi8i/JH/IZtFkiEmEQ1PgmhA==", - "dev": true - }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cacheable-request": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", - "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", - "dev": true, - "dependencies": { - "clone-response": "1.0.2", - "get-stream": "3.0.0", - "http-cache-semantics": "3.8.1", - "keyv": "3.0.0", - "lowercase-keys": "1.0.0", - "normalize-url": "2.0.1", - "responselike": "1.0.2" - } - }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", - "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.0" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "node_modules/caw": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", - "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", - "dev": true, - "dependencies": { - "get-proxy": "^2.0.0", - "isurl": "^1.0.0-alpha5", - "tunnel-agent": "^0.6.0", - "url-to-options": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cbor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-5.1.0.tgz", - "integrity": "sha512-qzEc7kUShdMbWTaUH7X+aHW8owvBU3FS0dfYR1lGYpoZr0mGJhhojLlZJH653x/DfeMZ56h315FRNBUIG1R7qg==", - "dev": true, - "dependencies": { - "bignumber.js": "^9.0.0", - "nofilter": "^1.0.4" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chai-bignumber": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chai-bignumber/-/chai-bignumber-3.0.0.tgz", - "integrity": "sha512-SubOtaSI2AILWTWe2j0c6i2yFT/f9J6UBjeVGDuwDiPLkF/U5+/eTWUE3sbCZ1KgcPF6UJsDVYbIxaYA097MQA==", - "dev": true - }, - "node_modules/chai-bn": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/chai-bn/-/chai-bn-0.2.1.tgz", - "integrity": "sha512-01jt2gSXAw7UYFPT5K8d7HYjdXj2vyeIuE+0T/34FWzlNcVbs1JkPxRu7rYMfQnJhrHT8Nr6qjSf5ZwwLU2EYg==", - "dev": true - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/checkpoint-store": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz", - "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", - "dev": true, - "dependencies": { - "functional-red-black-tree": "^1.0.1" - } - }, - "node_modules/chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.1.2" - } - }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cli-table3": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", - "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", - "dev": true, - "dependencies": { - "colors": "^1.1.2", - "object-assign": "^4.1.0", - "string-width": "^2.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "dev": true - }, - "node_modules/command-line-args": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-4.0.7.tgz", - "integrity": "sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA==", - "dev": true, - "dependencies": { - "array-back": "^2.0.0", - "find-replace": "^1.0.3", - "typical": "^2.6.1" - }, - "bin": { - "command-line-args": "bin/cli.js" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "dev": true - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concat-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/concat-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/concat-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/config-chain": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", - "dev": true, - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-disposition/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "node_modules/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", - "dev": true - }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/core-js-pure": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.7.0.tgz", - "integrity": "sha512-EZD2ckZysv8MMt4J6HSvS9K2GdtlZtdBncKAmF9lr2n0c9dJUaUN88PSTjvgwCgQPWKTkERXITgS6JJRAnljtg==", - "dev": true, - "hasInstallScript": true - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cosmiconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", - "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cosmiconfig/node_modules/parse-json": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", - "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cosmiconfig/node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/cross-spawn/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/death": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", - "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=", - "dev": true - }, - "node_modules/debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/decompress": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", - "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", - "dev": true, - "dependencies": { - "decompress-tar": "^4.0.0", - "decompress-tarbz2": "^4.0.0", - "decompress-targz": "^4.0.0", - "decompress-unzip": "^4.0.1", - "graceful-fs": "^4.1.10", - "make-dir": "^1.0.0", - "pify": "^2.3.0", - "strip-dirs": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tar": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", - "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", - "dev": true, - "dependencies": { - "file-type": "^5.2.0", - "is-stream": "^1.1.0", - "tar-stream": "^1.5.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tar/node_modules/file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tarbz2": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", - "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", - "dev": true, - "dependencies": { - "decompress-tar": "^4.1.0", - "file-type": "^6.1.0", - "is-stream": "^1.1.0", - "seek-bzip": "^1.0.5", - "unbzip2-stream": "^1.0.9" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tarbz2/node_modules/file-type": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", - "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-targz": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", - "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", - "dev": true, - "dependencies": { - "decompress-tar": "^4.1.1", - "file-type": "^5.2.0", - "is-stream": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-targz/node_modules/file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-unzip": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", - "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", - "dev": true, - "dependencies": { - "file-type": "^3.8.0", - "get-stream": "^2.2.0", - "pify": "^2.3.0", - "yauzl": "^2.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-unzip/node_modules/file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-unzip/node_modules/get-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", - "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", - "dev": true, - "dependencies": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-unzip/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "node_modules/deepmerge": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, - "node_modules/deferred-leveldown": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", - "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", - "dev": true, - "dependencies": { - "abstract-leveldown": "~2.6.0" - } - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-properties/node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "node_modules/detect-port": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", - "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", - "dev": true, - "dependencies": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "bin": { - "detect": "bin/detect-port", - "detect-port": "bin/detect-port" - }, - "engines": { - "node": ">= 4.2.1" - } - }, - "node_modules/detect-port/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/detect-port/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dir-glob/node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dir-to-object": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-to-object/-/dir-to-object-2.0.0.tgz", - "integrity": "sha512-sXs0JKIhymON7T1UZuO2Ud6VTNAx/VTBXIl4+3mjb2RgfOpt+hectX0x04YqPOPdkeOAKoJuKqwqnXXURNPNEA==", - "dev": true - }, - "node_modules/dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", - "dev": true - }, - "node_modules/dotenv": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", - "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/download": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", - "integrity": "sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==", - "dev": true, - "dependencies": { - "archive-type": "^4.0.0", - "caw": "^2.0.1", - "content-disposition": "^0.5.2", - "decompress": "^4.2.0", - "ext-name": "^5.0.0", - "file-type": "^8.1.0", - "filenamify": "^2.0.0", - "get-stream": "^3.0.0", - "got": "^8.3.1", - "make-dir": "^1.2.0", - "p-event": "^2.1.0", - "pify": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/drbg.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", - "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", - "dev": true, - "dependencies": { - "browserify-aes": "^1.0.6", - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "node_modules/elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", - "dev": true, - "dependencies": { - "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" - } - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/encoding-down": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", - "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", - "dev": true, - "dependencies": { - "abstract-leveldown": "^5.0.0", - "inherits": "^2.0.3", - "level-codec": "^9.0.0", - "level-errors": "^2.0.0", - "xtend": "^4.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/encoding-down/node_modules/abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/encoding-down/node_modules/level-codec": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", - "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", - "dev": true, - "dependencies": { - "buffer": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/encoding-down/node_modules/level-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", - "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", - "dev": true, - "dependencies": { - "errno": "~0.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/encoding-down/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/env-paths": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", - "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-abstract/node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "dependencies": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=0.12.0" - }, - "optionalDependencies": { - "source-map": "~0.2.0" - } - }, - "node_modules/escodegen/node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "dependencies": { - "amdefine": ">=0.0.4" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.7.0.tgz", - "integrity": "sha512-CStQYJgALoQBw3FsBzH0VOVDRnJ/ZimUlpLm226U8qgqYJfPOY/CPK6wyRInMxh73HSKg5wyRwdS4BVYYHwokA==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.1", - "jest-docblock": "^21.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima-extract-comments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz", - "integrity": "sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw==", - "dev": true, - "dependencies": { - "esprima": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eth-ens-namehash": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", - "integrity": "sha1-IprEbsqG1S4MmR58sq74P/D2i88=", - "dev": true, - "dependencies": { - "idna-uts46-hx": "^2.3.1", - "js-sha3": "^0.5.7" - } - }, - "node_modules/eth-ens-namehash/node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, - "node_modules/eth-gas-reporter": { - "version": "0.2.19", - "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.19.tgz", - "integrity": "sha512-yQmbAa6O9/Yl/syNml2A0R+ZLQnJ9m9jogFXHzjMWVBMUVnAcEskOVyxaMYddkclZdYIMxE99tQy830C2jLsAQ==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.0.0-beta.146", - "@solidity-parser/parser": "^0.8.0", - "cli-table3": "^0.5.0", - "colors": "^1.1.2", - "ethereumjs-util": "6.2.0", - "ethers": "^4.0.40", - "fs-readdir-recursive": "^1.1.0", - "lodash": "^4.17.14", - "markdown-table": "^1.1.3", - "mocha": "^7.1.1", - "req-cwd": "^2.0.0", - "request": "^2.88.0", - "request-promise-native": "^1.0.5", - "sha1": "^1.1.1", - "sync-request": "^6.0.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/@solidity-parser/parser": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.8.2.tgz", - "integrity": "sha512-8LySx3qrNXPgB5JiULfG10O3V7QTxI/TLzSw5hFQhXWSkVxZBAv4rZQ0sYgLEbc8g3L2lmnujj1hKul38Eu5NQ==", - "dev": true - }, - "node_modules/eth-gas-reporter/node_modules/ethereumjs-util": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz", - "integrity": "sha512-vb0XN9J2QGdZGIEKG2vXM+kUdEivUfU6Wmi5y0cg+LRhDYKnXIZ/Lz7XjFbHRR9VIKq2lVGLzGBkA++y2nOdOQ==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "ethjs-util": "0.1.6", - "keccak": "^2.0.0", - "rlp": "^2.2.3", - "secp256k1": "^3.0.1" - } - }, - "node_modules/eth-gas-reporter/node_modules/ethers": { - "version": "4.0.48", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.48.tgz", - "integrity": "sha512-sZD5K8H28dOrcidzx9f8KYh8083n5BexIO3+SbE4jK83L85FxtpXZBCQdXb8gkg+7sBqomcLhhkU7UHL+F7I2g==", - "dev": true, - "dependencies": { - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "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" - } - }, - "node_modules/eth-gas-reporter/node_modules/hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, - "node_modules/eth-gas-reporter/node_modules/keccak": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", - "integrity": "sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.5.0", - "inherits": "^2.0.4", - "nan": "^2.14.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=5.12.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/scrypt-js": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", - "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", - "dev": true - }, - "node_modules/eth-gas-reporter/node_modules/secp256k1": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz", - "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.5.0", - "bip66": "^1.1.5", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "drbg.js": "^1.0.1", - "elliptic": "^6.5.2", - "nan": "^2.14.0", - "safe-buffer": "^5.1.2" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", - "dev": true - }, - "node_modules/eth-gas-reporter/node_modules/uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", - "dev": true - }, - "node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/eth-sig-util": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.5.3.tgz", - "integrity": "sha512-KpXbCKmmBUNUTGh9MRKmNkIPietfhzBqqYqysDavLseIiMUGl95k6UcPEkALAZlj41e9E6yioYXc1PC333RKqw==", - "dev": true, - "dependencies": { - "buffer": "^5.2.1", - "elliptic": "^6.4.0", - "ethereumjs-abi": "0.6.5", - "ethereumjs-util": "^5.1.1", - "tweetnacl": "^1.0.0", - "tweetnacl-util": "^0.15.0" - } - }, - "node_modules/eth-sig-util/node_modules/ethereumjs-abi": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz", - "integrity": "sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=", - "dev": true, - "dependencies": { - "bn.js": "^4.10.0", - "ethereumjs-util": "^4.3.0" - } - }, - "node_modules/eth-sig-util/node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz", - "integrity": "sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w==", - "dev": true, - "dependencies": { - "bn.js": "^4.8.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "rlp": "^2.0.0" - } - }, - "node_modules/eth-sig-util/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ethashjs": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ethashjs/-/ethashjs-0.0.8.tgz", - "integrity": "sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw==", - "dev": true, - "dependencies": { - "async": "^2.1.2", - "buffer-xor": "^2.0.1", - "ethereumjs-util": "^7.0.2", - "miller-rabin": "^4.0.0" - } - }, - "node_modules/ethashjs/node_modules/buffer-xor": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", - "integrity": "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ethereum-bloom-filters": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.7.tgz", - "integrity": "sha512-cDcJJSJ9GMAcURiAWO3DxIEhTL/uWqlQnvgKpuYQzYPrt/izuGU+1ntQmHt0IRq6ADoSYHFnB+aCEFIldjhkMQ==", - "dev": true, - "dependencies": { - "js-sha3": "^0.8.0" - } - }, - "node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/ethereum-waffle": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/ethereum-waffle/-/ethereum-waffle-3.0.2.tgz", - "integrity": "sha512-VJQTL9oBbHIQRxQFuh1NBXoFXSlTIY6DrkPpO7CvevXRI9ixxq01nSc6hPYUIVy7s+U03sp4ply497O6mD3gsQ==", - "dev": true, - "dependencies": { - "@ethereum-waffle/chai": "^3.0.2", - "@ethereum-waffle/compiler": "^3.0.2", - "@ethereum-waffle/mock-contract": "^3.0.2", - "@ethereum-waffle/provider": "^3.0.2", - "ethers": "^5.0.1" - }, - "bin": { - "waffle": "bin/waffle" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/ethereumjs-abi": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", - "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ethereumjs-account": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz", - "integrity": "sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA==", - "dev": true, - "dependencies": { - "ethereumjs-util": "^6.0.0", - "rlp": "^2.2.1", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ethereumjs-account/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ethereumjs-block": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", - "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", - "dev": true, - "dependencies": { - "async": "^2.0.1", - "ethereumjs-common": "^1.5.0", - "ethereumjs-tx": "^2.1.1", - "ethereumjs-util": "^5.0.0", - "merkle-patricia-tree": "^2.1.2" - } - }, - "node_modules/ethereumjs-block/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ethereumjs-block/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/ethereumjs-block/node_modules/merkle-patricia-tree": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", - "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", - "dev": true, - "dependencies": { - "async": "^1.4.2", - "ethereumjs-util": "^5.0.0", - "level-ws": "0.0.0", - "levelup": "^1.2.1", - "memdown": "^1.0.0", - "readable-stream": "^2.0.0", - "rlp": "^2.0.0", - "semaphore": ">=1.0.1" - } - }, - "node_modules/ethereumjs-block/node_modules/merkle-patricia-tree/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/ethereumjs-block/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/ethereumjs-block/node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ethereumjs-block/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/ethereumjs-block/node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ethereumjs-blockchain": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz", - "integrity": "sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ==", - "dev": true, - "dependencies": { - "async": "^2.6.1", - "ethashjs": "~0.0.7", - "ethereumjs-block": "~2.2.2", - "ethereumjs-common": "^1.5.0", - "ethereumjs-util": "^6.1.0", - "flow-stoplight": "^1.0.0", - "level-mem": "^3.0.1", - "lru-cache": "^5.1.1", - "rlp": "^2.2.2", - "semaphore": "^1.1.0" - } - }, - "node_modules/ethereumjs-blockchain/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ethereumjs-common": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz", - "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==", - "dev": true - }, - "node_modules/ethereumjs-tx": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", - "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", - "dev": true, - "dependencies": { - "ethereumjs-common": "^1.5.0", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ethereumjs-tx/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ethereumjs-util": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.2.tgz", - "integrity": "sha512-ATAP02eJLpAlWGfiKQddNrRfZpwXiTFhRN2EM/yLXMCdBW/xjKYblNKcx8GLzzrjXg0ymotck+lam1nuV90arQ==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^5.1.2", - "create-hash": "^1.1.2", - "ethjs-util": "0.1.6", - "keccak": "^3.0.0", - "rlp": "^2.2.4", - "secp256k1": "^4.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ethereumjs-util/node_modules/bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true - }, - "node_modules/ethers": { - "version": "5.0.19", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.0.19.tgz", - "integrity": "sha512-0AZnUgZh98q888WAd1oI3aLeI+iyDtrupjANVtPPS7O63lVopkR/No8A1NqSkgl/rU+b2iuu2mUZor6GD4RG2w==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "5.0.7", - "@ethersproject/abstract-provider": "5.0.5", - "@ethersproject/abstract-signer": "5.0.7", - "@ethersproject/address": "5.0.5", - "@ethersproject/base64": "5.0.4", - "@ethersproject/basex": "5.0.4", - "@ethersproject/bignumber": "5.0.8", - "@ethersproject/bytes": "5.0.5", - "@ethersproject/constants": "5.0.5", - "@ethersproject/contracts": "5.0.5", - "@ethersproject/hash": "5.0.6", - "@ethersproject/hdnode": "5.0.5", - "@ethersproject/json-wallets": "5.0.7", - "@ethersproject/keccak256": "5.0.4", - "@ethersproject/logger": "5.0.6", - "@ethersproject/networks": "5.0.4", - "@ethersproject/pbkdf2": "5.0.4", - "@ethersproject/properties": "5.0.4", - "@ethersproject/providers": "5.0.14", - "@ethersproject/random": "5.0.4", - "@ethersproject/rlp": "5.0.4", - "@ethersproject/sha2": "5.0.4", - "@ethersproject/signing-key": "5.0.5", - "@ethersproject/solidity": "5.0.5", - "@ethersproject/strings": "5.0.5", - "@ethersproject/transactions": "5.0.6", - "@ethersproject/units": "5.0.6", - "@ethersproject/wallet": "5.0.7", - "@ethersproject/web": "5.0.9", - "@ethersproject/wordlists": "5.0.5" - } - }, - "node_modules/ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", - "dev": true, - "dependencies": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ethjs-unit/node_modules/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true - }, - "node_modules/ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", - "dev": true - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/execa": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz", - "integrity": "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^3.0.0", - "onetime": "^5.1.0", - "p-finally": "^2.0.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": "^8.12.0 || >=9.7.0" - } - }, - "node_modules/execa/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/execa/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/p-finally": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", - "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dev": true, - "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/express/node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/express/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "dependencies": { - "type": "^2.0.0" - } - }, - "node_modules/ext-list": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", - "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", - "dev": true, - "dependencies": { - "mime-db": "^1.28.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ext-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", - "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", - "dev": true, - "dependencies": { - "ext-list": "^2.0.0", - "sort-keys-length": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", - "dev": true - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extract-comments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/extract-comments/-/extract-comments-1.1.0.tgz", - "integrity": "sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q==", - "dev": true, - "dependencies": { - "esprima-extract-comments": "^1.1.0", - "parse-code-context": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fake-merkle-patricia-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz", - "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", - "dev": true, - "dependencies": { - "checkpoint-store": "^1.1.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", - "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fastq": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz", - "integrity": "sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/file-type": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", - "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true - }, - "node_modules/filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/filenamify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", - "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", - "dev": true, - "dependencies": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.0", - "trim-repeated": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/find-replace": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-1.0.3.tgz", - "integrity": "sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A=", - "dev": true, - "dependencies": { - "array-back": "^1.0.4", - "test-value": "^2.1.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/find-replace/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/find-versions": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", - "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", - "dev": true, - "dependencies": { - "semver-regex": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-yarn-workspace-root": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz", - "integrity": "sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==", - "dev": true, - "dependencies": { - "fs-extra": "^4.0.3", - "micromatch": "^3.1.4" - } - }, - "node_modules/find-yarn-workspace-root/node_modules/fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "node_modules/flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dev": true, - "dependencies": { - "is-buffer": "~2.0.3" - }, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flow-stoplight": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz", - "integrity": "sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s=", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", - "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fp-ts": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", - "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", - "dev": true - }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "node_modules/from2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/from2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/from2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/from2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "dependencies": { - "minipass": "^2.6.0" - } - }, - "node_modules/fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/ganache-cli": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.9.0.tgz", - "integrity": "sha512-ZdL6kPrApXF/O+f6uU431OJcwxMk69H3KPDSHHrMP82ZvZRNpDHbR+rVv7XX/YUeoQ5q6nZ2AFiGiFAVn9pfzA==", - "dev": true, - "dependencies": { - "ethereumjs-util": "6.1.0", - "source-map-support": "0.5.12", - "yargs": "13.2.4" - }, - "bin": { - "ganache-cli": "cli.js" - } - }, - "node_modules/ganache-cli/node_modules/ansi-regex": { - "version": "4.1.0", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/ansi-styles": { - "version": "3.2.1", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/bindings": { - "version": "1.5.0", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/ganache-cli/node_modules/bip66": { - "version": "1.1.5", - "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ganache-cli/node_modules/bn.js": { - "version": "4.11.8", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/ganache-cli/node_modules/brorand": { - "version": "1.1.0", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "node_modules/ganache-cli/node_modules/browserify-aes": { - "version": "1.2.0", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ganache-cli/node_modules/buffer-from": { - "version": "1.1.1", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "node_modules/ganache-cli/node_modules/buffer-xor": { - "version": "1.0.3", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "node_modules/ganache-cli/node_modules/camelcase": { - "version": "5.3.1", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/cipher-base": { - "version": "1.0.4", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ganache-cli/node_modules/cliui": { - "version": "5.0.0", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/ganache-cli/node_modules/color-convert": { - "version": "1.9.3", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/ganache-cli/node_modules/color-name": { - "version": "1.1.3", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/ganache-cli/node_modules/create-hash": { - "version": "1.2.0", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/ganache-cli/node_modules/create-hmac": { - "version": "1.1.7", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/ganache-cli/node_modules/cross-spawn": { - "version": "6.0.5", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/ganache-cli/node_modules/decamelize": { - "version": "1.2.0", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/drbg.js": { - "version": "1.0.1", - "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", - "dev": true, - "dependencies": { - "browserify-aes": "^1.0.6", - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/ganache-cli/node_modules/elliptic": { - "version": "6.5.0", - "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", - "dev": true, - "dependencies": { - "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" - } - }, - "node_modules/ganache-cli/node_modules/emoji-regex": { - "version": "7.0.3", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/ganache-cli/node_modules/end-of-stream": { - "version": "1.4.1", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/ganache-cli/node_modules/ethereumjs-util": { - "version": "6.1.0", - "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "ethjs-util": "0.1.6", - "keccak": "^1.0.2", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1", - "secp256k1": "^3.0.1" - } - }, - "node_modules/ganache-cli/node_modules/ethjs-util": { - "version": "0.1.6", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ganache-cli/node_modules/evp_bytestokey": { - "version": "1.0.3", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-cli/node_modules/execa": { - "version": "1.0.0", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/file-uri-to-path": { - "version": "1.0.0", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true - }, - "node_modules/ganache-cli/node_modules/find-up": { - "version": "3.0.0", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/get-caller-file": { - "version": "2.0.5", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/ganache-cli/node_modules/get-stream": { - "version": "4.1.0", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/hash-base": { - "version": "3.0.4", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/hash.js": { - "version": "1.1.7", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/ganache-cli/node_modules/hmac-drbg": { - "version": "1.0.1", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/ganache-cli/node_modules/inherits": { - "version": "2.0.4", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ganache-cli/node_modules/invert-kv": { - "version": "2.0.0", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/is-hex-prefixed": { - "version": "1.0.0", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", - "dev": true, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ganache-cli/node_modules/is-stream": { - "version": "1.1.0", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/isexe": { - "version": "2.0.0", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/ganache-cli/node_modules/keccak": { - "version": "1.4.0", - "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.2.1", - "inherits": "^2.0.3", - "nan": "^2.2.1", - "safe-buffer": "^5.1.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/ganache-cli/node_modules/lcid": { - "version": "2.0.0", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "dependencies": { - "invert-kv": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/locate-path": { - "version": "3.0.0", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/map-age-cleaner": { - "version": "0.1.3", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "dependencies": { - "p-defer": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/md5.js": { - "version": "1.3.5", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/ganache-cli/node_modules/mem": { - "version": "4.3.0", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "dependencies": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/mimic-fn": { - "version": "2.1.0", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/minimalistic-assert": { - "version": "1.0.1", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/ganache-cli/node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "node_modules/ganache-cli/node_modules/nan": { - "version": "2.14.0", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true - }, - "node_modules/ganache-cli/node_modules/nice-try": { - "version": "1.0.5", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/ganache-cli/node_modules/npm-run-path": { - "version": "2.0.2", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/once": { - "version": "1.4.0", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/ganache-cli/node_modules/os-locale": { - "version": "3.1.0", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "dependencies": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/p-defer": { - "version": "1.0.0", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/p-finally": { - "version": "1.0.0", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/p-is-promise": { - "version": "2.1.0", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/p-limit": { - "version": "2.2.0", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/p-locate": { - "version": "3.0.0", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/p-try": { - "version": "2.2.0", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/path-exists": { - "version": "3.0.0", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/path-key": { - "version": "2.0.1", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/pump": { - "version": "3.0.0", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/ganache-cli/node_modules/require-directory": { - "version": "2.1.1", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/require-main-filename": { - "version": "2.0.0", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/ganache-cli/node_modules/ripemd160": { - "version": "2.0.2", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/ganache-cli/node_modules/rlp": { - "version": "2.2.3", - "integrity": "sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.1", - "safe-buffer": "^5.1.1" - }, - "bin": { - "rlp": "bin/rlp" - } - }, - "node_modules/ganache-cli/node_modules/safe-buffer": { - "version": "5.2.0", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", - "dev": true - }, - "node_modules/ganache-cli/node_modules/secp256k1": { - "version": "3.7.1", - "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.5.0", - "bip66": "^1.1.5", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "drbg.js": "^1.0.1", - "elliptic": "^6.4.1", - "nan": "^2.14.0", - "safe-buffer": "^5.1.2" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/ganache-cli/node_modules/semver": { - "version": "5.7.0", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ganache-cli/node_modules/set-blocking": { - "version": "2.0.0", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/ganache-cli/node_modules/sha.js": { - "version": "2.4.11", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/ganache-cli/node_modules/shebang-command": { - "version": "1.2.0", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/shebang-regex": { - "version": "1.0.0", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/signal-exit": { - "version": "3.0.2", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "node_modules/ganache-cli/node_modules/source-map": { - "version": "0.6.1", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/source-map-support": { - "version": "0.5.12", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/ganache-cli/node_modules/string-width": { - "version": "3.1.0", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/strip-ansi": { - "version": "5.2.0", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/strip-eof": { - "version": "1.0.0", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/strip-hex-prefix": { - "version": "1.0.0", - "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ganache-cli/node_modules/which": { - "version": "1.3.1", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/ganache-cli/node_modules/which-module": { - "version": "2.0.0", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/ganache-cli/node_modules/wrap-ansi": { - "version": "5.1.0", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/wrappy": { - "version": "1.0.2", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/ganache-cli/node_modules/y18n": { - "version": "4.0.0", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "node_modules/ganache-cli/node_modules/yargs": { - "version": "13.2.4", - "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.0" - } - }, - "node_modules/ganache-cli/node_modules/yargs-parser": { - "version": "13.1.1", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/ganache-core": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/ganache-core/-/ganache-core-2.13.1.tgz", - "integrity": "sha512-Ewg+kNcDqXtOohe7jCcP+ZUv9EMzOx2MoqOYYP3BCfxrDh3KjBXXaKK+Let7li0TghAs9lxmBgevZku35j5YzA==", - "dev": true, - "dependencies": { - "abstract-leveldown": "3.0.0", - "async": "2.6.2", - "bip39": "2.5.0", - "cachedown": "1.0.0", - "clone": "2.1.2", - "debug": "3.2.6", - "encoding-down": "5.0.4", - "eth-sig-util": "^2.0.0", - "ethereumjs-abi": "0.6.8", - "ethereumjs-account": "3.0.0", - "ethereumjs-block": "2.2.2", - "ethereumjs-common": "1.5.0", - "ethereumjs-tx": "2.1.2", - "ethereumjs-util": "6.2.1", - "ethereumjs-vm": "4.2.0", - "heap": "0.2.6", - "keccak": "3.0.1", - "level-sublevel": "6.6.4", - "levelup": "3.1.1", - "lodash": "4.17.20", - "lru-cache": "5.1.1", - "merkle-patricia-tree": "3.0.0", - "patch-package": "6.2.2", - "seedrandom": "3.0.1", - "source-map-support": "0.5.12", - "tmp": "0.1.0", - "web3-provider-engine": "14.2.1", - "websocket": "1.0.32" - }, - "engines": { - "node": ">=8.9.0" - }, - "optionalDependencies": { - "ethereumjs-wallet": "0.6.5", - "web3": "1.2.11" - } - }, - "node_modules/ganache-core/node_modules/@ethersproject/abi": { - "version": "5.0.0-beta.153", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz", - "integrity": "sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/address": ">=5.0.0-beta.128", - "@ethersproject/bignumber": ">=5.0.0-beta.130", - "@ethersproject/bytes": ">=5.0.0-beta.129", - "@ethersproject/constants": ">=5.0.0-beta.128", - "@ethersproject/hash": ">=5.0.0-beta.128", - "@ethersproject/keccak256": ">=5.0.0-beta.127", - "@ethersproject/logger": ">=5.0.0-beta.129", - "@ethersproject/properties": ">=5.0.0-beta.131", - "@ethersproject/strings": ">=5.0.0-beta.130" - } - }, - "node_modules/ganache-core/node_modules/@ethersproject/address": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.5.tgz", - "integrity": "sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/rlp": "^5.0.3", - "bn.js": "^4.4.0" - } - }, - "node_modules/ganache-core/node_modules/@ethersproject/bignumber": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.8.tgz", - "integrity": "sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "bn.js": "^4.4.0" - } - }, - "node_modules/ganache-core/node_modules/@ethersproject/bytes": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.5.tgz", - "integrity": "sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/logger": "^5.0.5" - } - }, - "node_modules/ganache-core/node_modules/@ethersproject/constants": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.5.tgz", - "integrity": "sha512-foaQVmxp2+ik9FrLUCtVrLZCj4M3Ibgkqvh+Xw/vFRSerkjVSYePApaVE5essxhoSlF1U9oXfWY09QI2AXtgKA==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/bignumber": "^5.0.7" - } - }, - "node_modules/ganache-core/node_modules/@ethersproject/hash": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.5.tgz", - "integrity": "sha512-GpI80/h2HDpfNKpCZoxQJCjOQloGnlD5hM1G+tZe8FQDJhEvFjJoPDuWv+NaYjJfOciKS2Axqc4Q4WamdLoUgg==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/strings": "^5.0.4" - } - }, - "node_modules/ganache-core/node_modules/@ethersproject/keccak256": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.4.tgz", - "integrity": "sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "js-sha3": "0.5.7" - } - }, - "node_modules/ganache-core/node_modules/@ethersproject/logger": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.6.tgz", - "integrity": "sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/@ethersproject/properties": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.4.tgz", - "integrity": "sha512-UdyX3GqBxFt15B0uSESdDNmhvEbK3ACdDXl2soshoPcneXuTswHDeA0LoPlnaZzhbgk4p6jqb4GMms5C26Qu6A==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/logger": "^5.0.5" - } - }, - "node_modules/ganache-core/node_modules/@ethersproject/rlp": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.4.tgz", - "integrity": "sha512-5qrrZad7VTjofxSsm7Zg/7Dr4ZOln4S2CqiDdOuTv6MBKnXj0CiBojXyuDy52M8O3wxH0CyE924hXWTDV1PQWQ==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5" - } - }, - "node_modules/ganache-core/node_modules/@ethersproject/signing-key": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.5.tgz", - "integrity": "sha512-Z1wY7JC1HVO4CvQWY2TyTTuAr8xK3bJijZw1a9G92JEmKdv1j255R/0YLBBcFTl2J65LUjtXynNJ2GbArPGi5g==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "elliptic": "6.5.3" - } - }, - "node_modules/ganache-core/node_modules/@ethersproject/strings": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.5.tgz", - "integrity": "sha512-JED6WaIV00xM/gvj8vSnd+0VWtDYdidTmavFRCTQakqfz+4tDo6Jz5LHgG+dd45h7ah7ykCHW0C7ZXWEDROCXQ==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/logger": "^5.0.5" - } - }, - "node_modules/ganache-core/node_modules/@ethersproject/transactions": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.6.tgz", - "integrity": "sha512-htsFhOD+NMBxx676A8ehSuwVV49iqpSB+CkjPZ02tpNew0K6p8g0CZ46Z1ZP946gIHAU80xQ0NACHYrjIUaCFA==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/rlp": "^5.0.3", - "@ethersproject/signing-key": "^5.0.4" - } - }, - "node_modules/ganache-core/node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "optional": true, - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ganache-core/node_modules/@types/node": { - "version": "14.11.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.8.tgz", - "integrity": "sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw==", - "dev": true - }, - "node_modules/ganache-core/node_modules/@types/pbkdf2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", - "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ganache-core/node_modules/@types/secp256k1": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", - "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ganache-core/node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/abstract-leveldown": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz", - "integrity": "sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "optional": true, - "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/aes-js": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", - "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/ajv": { - "version": "6.12.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", - "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "node_modules/ganache-core/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/ganache-core/node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/ganache-core/node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/ganache-core/node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "dependencies": { - "lodash": "^4.17.11" - } - }, - "node_modules/ganache-core/node_modules/async-eventemitter": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", - "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", - "dev": true, - "dependencies": { - "async": "^2.4.0" - } - }, - "node_modules/ganache-core/node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/ganache-core/node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/ganache-core/node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ganache-core/node_modules/aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", - "dev": true - }, - "node_modules/ganache-core/node_modules/babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "dependencies": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/babel-code-frame/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/ganache-core/node_modules/babel-core": { - "version": "6.26.3", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "dev": true, - "dependencies": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" - } - }, - "node_modules/ganache-core/node_modules/babel-core/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/ganache-core/node_modules/babel-core/node_modules/json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/ganache-core/node_modules/babel-core/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/ganache-core/node_modules/babel-core/node_modules/slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "dependencies": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - } - }, - "node_modules/ganache-core/node_modules/babel-generator/node_modules/jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/ganache-core/node_modules/babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "dependencies": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "dependencies": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "dependencies": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "node_modules/ganache-core/node_modules/babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "dependencies": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "node_modules/ganache-core/node_modules/babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "dependencies": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, - "dependencies": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true - }, - "node_modules/ganache-core/node_modules/babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true - }, - "node_modules/ganache-core/node_modules/babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, - "dependencies": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "dependencies": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "dependencies": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "dependencies": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true, - "dependencies": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "dependencies": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "dependencies": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "dependencies": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "dependencies": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "dependencies": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, - "dependencies": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "dependencies": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, - "dependencies": { - "regenerator-transform": "^0.10.0" - } - }, - "node_modules/ganache-core/node_modules/babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "node_modules/ganache-core/node_modules/babel-preset-env": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", - "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "dev": true, - "dependencies": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-to-generator": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.23.0", - "babel-plugin-transform-es2015-classes": "^6.23.0", - "babel-plugin-transform-es2015-computed-properties": "^6.22.0", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", - "babel-plugin-transform-es2015-for-of": "^6.23.0", - "babel-plugin-transform-es2015-function-name": "^6.22.0", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-umd": "^6.23.0", - "babel-plugin-transform-es2015-object-super": "^6.22.0", - "babel-plugin-transform-es2015-parameters": "^6.23.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", - "babel-plugin-transform-exponentiation-operator": "^6.22.0", - "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^3.2.6", - "invariant": "^2.2.2", - "semver": "^5.3.0" - } - }, - "node_modules/ganache-core/node_modules/babel-preset-env/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ganache-core/node_modules/babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, - "dependencies": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" - } - }, - "node_modules/ganache-core/node_modules/babel-register/node_modules/source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "dependencies": { - "source-map": "^0.5.6" - } - }, - "node_modules/ganache-core/node_modules/babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "node_modules/ganache-core/node_modules/babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "node_modules/ganache-core/node_modules/babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "dependencies": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - } - }, - "node_modules/ganache-core/node_modules/babel-traverse/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/ganache-core/node_modules/babel-traverse/node_modules/globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/babel-traverse/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/ganache-core/node_modules/babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "node_modules/ganache-core/node_modules/babel-types/node_modules/to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/babelify": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", - "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", - "dev": true, - "dependencies": { - "babel-core": "^6.0.14", - "object-assign": "^4.0.0" - } - }, - "node_modules/ganache-core/node_modules/babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true, - "bin": { - "babylon": "bin/babylon.js" - } - }, - "node_modules/ganache-core/node_modules/backoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", - "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", - "dev": true, - "dependencies": { - "precond": "0.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "node_modules/ganache-core/node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/base-x": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", - "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ganache-core/node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", - "dev": true - }, - "node_modules/ganache-core/node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/ganache-core/node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "node_modules/ganache-core/node_modules/bignumber.js": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", - "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", - "dev": true, - "optional": true, - "engines": { - "node": "*" - } - }, - "node_modules/ganache-core/node_modules/bip39": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-2.5.0.tgz", - "integrity": "sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA==", - "dev": true, - "dependencies": { - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1", - "safe-buffer": "^5.0.1", - "unorm": "^1.3.3" - } - }, - "node_modules/ganache-core/node_modules/blakejs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", - "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=", - "dev": true - }, - "node_modules/ganache-core/node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - }, - "node_modules/ganache-core/node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "optional": true, - "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ganache-core/node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "optional": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/ganache-core/node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/body-parser/node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/ganache-core/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/ganache-core/node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "node_modules/ganache-core/node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ganache-core/node_modules/browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "optional": true, - "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "node_modules/ganache-core/node_modules/browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "optional": true, - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/ganache-core/node_modules/browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } - }, - "node_modules/ganache-core/node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "node_modules/ganache-core/node_modules/browserify-sign/node_modules/bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/browserify-sign/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "optional": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ganache-core/node_modules/browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - }, - "bin": { - "browserslist": "cli.js" - } - }, - "node_modules/ganache-core/node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", - "dev": true, - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/ganache-core/node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dev": true, - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/ganache-core/node_modules/buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "dev": true, - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "node_modules/ganache-core/node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "node_modules/ganache-core/node_modules/buffer-to-arraybuffer": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "node_modules/ganache-core/node_modules/bufferutil": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", - "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-gyp-build": "~3.7.0" - } - }, - "node_modules/ganache-core/node_modules/bufferutil/node_modules/node-gyp-build": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", - "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", - "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/ganache-core/node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ganache-core/node_modules/bytewise": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", - "integrity": "sha1-HRPL/3F65xWAlKqIGzXQgbOHJT4=", - "dev": true, - "dependencies": { - "bytewise-core": "^1.2.2", - "typewise": "^1.0.3" - } - }, - "node_modules/ganache-core/node_modules/bytewise-core": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz", - "integrity": "sha1-P7QQx+kVWOsasiqCg0V3qmvWHUI=", - "dev": true, - "dependencies": { - "typewise-core": "^1.2" - } - }, - "node_modules/ganache-core/node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "optional": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ganache-core/node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ganache-core/node_modules/cachedown": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cachedown/-/cachedown-1.0.0.tgz", - "integrity": "sha1-1D8DbkUQaWsxJG19sx6/D3rDLRU=", - "dev": true, - "dependencies": { - "abstract-leveldown": "^2.4.1", - "lru-cache": "^3.2.0" - } - }, - "node_modules/ganache-core/node_modules/cachedown/node_modules/abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/cachedown/node_modules/lru-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", - "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.1" - } - }, - "node_modules/ganache-core/node_modules/caniuse-lite": { - "version": "1.0.30001146", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001146.tgz", - "integrity": "sha512-VAy5RHDfTJhpxnDdp2n40GPPLp3KqNrXz1QqFv4J64HvArKs8nuNMOWkB3ICOaBTU/Aj4rYAo/ytdQDDFF/Pug==", - "dev": true - }, - "node_modules/ganache-core/node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "node_modules/ganache-core/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/checkpoint-store": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz", - "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", - "dev": true, - "dependencies": { - "functional-red-black-tree": "^1.0.1" - } - }, - "node_modules/ganache-core/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/cids": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", - "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", - "dev": true, - "optional": true, - "dependencies": { - "buffer": "^5.5.0", - "class-is": "^1.1.0", - "multibase": "~0.6.0", - "multicodec": "^1.0.0", - "multihashes": "~0.4.15" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/ganache-core/node_modules/cids/node_modules/multicodec": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", - "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", - "dev": true, - "optional": true, - "dependencies": { - "buffer": "^5.6.0", - "varint": "^5.0.0" - } - }, - "node_modules/ganache-core/node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ganache-core/node_modules/class-is": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", - "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/class-utils/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/class-utils/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/ganache-core/node_modules/class-utils/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/class-utils/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/class-utils/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/ganache-core/node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "optional": true, - "dependencies": { - "mimic-response": "^1.0.0" - } - }, - "node_modules/ganache-core/node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/ganache-core/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/ganache-core/node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ganache-core/node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/ganache-core/node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/ganache-core/node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/ganache-core/node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/content-disposition/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/content-hash": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", - "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", - "dev": true, - "optional": true, - "dependencies": { - "cids": "^0.7.1", - "multicodec": "^0.5.5", - "multihashes": "^0.4.15" - } - }, - "node_modules/ganache-core/node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/ganache-core/node_modules/convert-source-map/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ganache-core/node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", - "dev": true, - "hasInstallScript": true - }, - "node_modules/ganache-core/node_modules/core-js-pure": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", - "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==", - "dev": true, - "hasInstallScript": true - }, - "node_modules/ganache-core/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "node_modules/ganache-core/node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "optional": true, - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ganache-core/node_modules/create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "node_modules/ganache-core/node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/ganache-core/node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/ganache-core/node_modules/cross-fetch": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.3.tgz", - "integrity": "sha512-PrWWNH3yL2NYIb/7WF/5vFG3DCQiXDOVf8k3ijatbrtnwNuhMWLC7YF7uqf53tbTFDzHIUD8oITw4Bxt8ST3Nw==", - "dev": true, - "dependencies": { - "node-fetch": "2.1.2", - "whatwg-fetch": "2.0.4" - } - }, - "node_modules/ganache-core/node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "optional": true, - "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ganache-core/node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/ganache-core/node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/ganache-core/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/ganache-core/node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/ganache-core/node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "optional": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "dependencies": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, - "node_modules/ganache-core/node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/deferred-leveldown": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", - "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", - "dev": true, - "dependencies": { - "abstract-leveldown": "~5.0.0", - "inherits": "^2.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/deferred-leveldown/node_modules/abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "node_modules/ganache-core/node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ganache-core/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "optional": true, - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/ganache-core/node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "dependencies": { - "repeating": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/ganache-core/node_modules/dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", - "dev": true - }, - "node_modules/ganache-core/node_modules/dotignore": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz", - "integrity": "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==", - "dev": true, - "dependencies": { - "minimatch": "^3.0.4" - }, - "bin": { - "ignored": "bin/ignored" - } - }, - "node_modules/ganache-core/node_modules/duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/ganache-core/node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/electron-to-chromium": { - "version": "1.3.578", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.578.tgz", - "integrity": "sha512-z4gU6dA1CbBJsAErW5swTGAaU2TBzc2mPAonJb00zqW1rOraDo2zfBMDRvaz9cVic+0JEZiYbHWPw/fTaZlG2Q==", - "dev": true - }, - "node_modules/ganache-core/node_modules/elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", - "dev": true, - "dependencies": { - "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" - } - }, - "node_modules/ganache-core/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ganache-core/node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/ganache-core/node_modules/encoding-down": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", - "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", - "dev": true, - "dependencies": { - "abstract-leveldown": "^5.0.0", - "inherits": "^2.0.3", - "level-codec": "^9.0.0", - "level-errors": "^2.0.0", - "xtend": "^4.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/encoding-down/node_modules/abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", - "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/ganache-core/node_modules/errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/ganache-core/node_modules/es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/ganache-core/node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/ganache-core/node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/ganache-core/node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/ganache-core/node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/eth-block-tracker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz", - "integrity": "sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug==", - "dev": true, - "dependencies": { - "eth-query": "^2.1.0", - "ethereumjs-tx": "^1.3.3", - "ethereumjs-util": "^5.1.3", - "ethjs-util": "^0.1.3", - "json-rpc-engine": "^3.6.0", - "pify": "^2.3.0", - "tape": "^4.6.3" - } - }, - "node_modules/ganache-core/node_modules/eth-block-tracker/node_modules/ethereumjs-tx": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", - "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", - "dev": true, - "dependencies": { - "ethereum-common": "^0.0.18", - "ethereumjs-util": "^5.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-block-tracker/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-block-tracker/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/eth-ens-namehash": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", - "integrity": "sha1-IprEbsqG1S4MmR58sq74P/D2i88=", - "dev": true, - "optional": true, - "dependencies": { - "idna-uts46-hx": "^2.3.1", - "js-sha3": "^0.5.7" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-infura": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz", - "integrity": "sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw==", - "dev": true, - "dependencies": { - "cross-fetch": "^2.1.1", - "eth-json-rpc-middleware": "^1.5.0", - "json-rpc-engine": "^3.4.0", - "json-rpc-error": "^2.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz", - "integrity": "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==", - "dev": true, - "dependencies": { - "async": "^2.5.0", - "eth-query": "^2.1.2", - "eth-tx-summary": "^3.1.2", - "ethereumjs-block": "^1.6.0", - "ethereumjs-tx": "^1.3.3", - "ethereumjs-util": "^5.1.2", - "ethereumjs-vm": "^2.1.0", - "fetch-ponyfill": "^4.0.0", - "json-rpc-engine": "^3.6.0", - "json-rpc-error": "^2.0.0", - "json-stable-stringify": "^1.0.1", - "promise-to-callback": "^1.0.0", - "tape": "^4.6.3" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/abstract-leveldown": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", - "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/deferred-leveldown": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", - "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", - "dev": true, - "dependencies": { - "abstract-leveldown": "~2.6.0" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-account": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", - "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", - "dev": true, - "dependencies": { - "ethereumjs-util": "^5.0.0", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-block": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", - "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", - "dev": true, - "dependencies": { - "async": "^2.0.1", - "ethereum-common": "0.2.0", - "ethereumjs-tx": "^1.2.2", - "ethereumjs-util": "^5.0.0", - "merkle-patricia-tree": "^2.1.2" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-block/node_modules/ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-tx": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", - "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", - "dev": true, - "dependencies": { - "ethereum-common": "^0.0.18", - "ethereumjs-util": "^5.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz", - "integrity": "sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==", - "dev": true, - "dependencies": { - "async": "^2.1.2", - "async-eventemitter": "^0.2.2", - "ethereumjs-account": "^2.0.3", - "ethereumjs-block": "~2.2.0", - "ethereumjs-common": "^1.1.0", - "ethereumjs-util": "^6.0.0", - "fake-merkle-patricia-tree": "^1.0.1", - "functional-red-black-tree": "^1.0.1", - "merkle-patricia-tree": "^2.3.2", - "rustbn.js": "~0.2.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm/node_modules/ethereumjs-block": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", - "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", - "dev": true, - "dependencies": { - "async": "^2.0.1", - "ethereumjs-common": "^1.5.0", - "ethereumjs-tx": "^2.1.1", - "ethereumjs-util": "^5.0.0", - "merkle-patricia-tree": "^2.1.2" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm/node_modules/ethereumjs-block/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm/node_modules/ethereumjs-tx": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", - "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", - "dev": true, - "dependencies": { - "ethereumjs-common": "^1.5.0", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ethereumjs-vm/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-codec": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", - "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-errors": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", - "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", - "dev": true, - "dependencies": { - "errno": "~0.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-iterator-stream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", - "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "level-errors": "^1.0.3", - "readable-stream": "^1.0.33", - "xtend": "^4.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-iterator-stream/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-ws": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", - "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", - "dev": true, - "dependencies": { - "readable-stream": "~1.0.15", - "xtend": "~2.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-ws/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/level-ws/node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/levelup": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", - "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", - "dev": true, - "dependencies": { - "deferred-leveldown": "~1.2.1", - "level-codec": "~7.0.0", - "level-errors": "~1.0.3", - "level-iterator-stream": "~1.3.0", - "prr": "~1.0.1", - "semver": "~5.4.1", - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/ltgt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/memdown": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", - "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", - "dev": true, - "dependencies": { - "abstract-leveldown": "~2.7.1", - "functional-red-black-tree": "^1.0.1", - "immediate": "^3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/memdown/node_modules/abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/merkle-patricia-tree": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", - "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", - "dev": true, - "dependencies": { - "async": "^1.4.2", - "ethereumjs-util": "^5.0.0", - "level-ws": "0.0.0", - "levelup": "^1.2.1", - "memdown": "^1.0.0", - "readable-stream": "^2.0.0", - "rlp": "^2.0.0", - "semaphore": ">=1.0.1" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/merkle-patricia-tree/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ganache-core/node_modules/eth-json-rpc-middleware/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-lib": { - "version": "0.1.29", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz", - "integrity": "sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "nano-json-stream-parser": "^0.1.2", - "servify": "^0.1.12", - "ws": "^3.0.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/ganache-core/node_modules/eth-query": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz", - "integrity": "sha1-1nQdkAAQa1FRDHLbktY2VFam2l4=", - "dev": true, - "dependencies": { - "json-rpc-random-id": "^1.0.0", - "xtend": "^4.0.1" - } - }, - "node_modules/ganache-core/node_modules/eth-sig-util": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.3.0.tgz", - "integrity": "sha512-ugD1AvaggvKaZDgnS19W5qOfepjGc7qHrt7TrAaL54gJw9SHvgIXJ3r2xOMW30RWJZNP+1GlTOy5oye7yXA4xA==", - "dev": true, - "dependencies": { - "buffer": "^5.2.1", - "elliptic": "^6.4.0", - "ethereumjs-abi": "0.6.5", - "ethereumjs-util": "^5.1.1", - "tweetnacl": "^1.0.0", - "tweetnacl-util": "^0.15.0" - } - }, - "node_modules/ganache-core/node_modules/eth-sig-util/node_modules/ethereumjs-abi": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz", - "integrity": "sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=", - "dev": true, - "dependencies": { - "bn.js": "^4.10.0", - "ethereumjs-util": "^4.3.0" - } - }, - "node_modules/ganache-core/node_modules/eth-sig-util/node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz", - "integrity": "sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w==", - "dev": true, - "dependencies": { - "bn.js": "^4.8.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "rlp": "^2.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-sig-util/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz", - "integrity": "sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg==", - "dev": true, - "dependencies": { - "async": "^2.1.2", - "clone": "^2.0.0", - "concat-stream": "^1.5.1", - "end-of-stream": "^1.1.0", - "eth-query": "^2.0.2", - "ethereumjs-block": "^1.4.1", - "ethereumjs-tx": "^1.1.1", - "ethereumjs-util": "^5.0.1", - "ethereumjs-vm": "^2.6.0", - "through2": "^2.0.3" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/abstract-leveldown": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", - "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/deferred-leveldown": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", - "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", - "dev": true, - "dependencies": { - "abstract-leveldown": "~2.6.0" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-account": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", - "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", - "dev": true, - "dependencies": { - "ethereumjs-util": "^5.0.0", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-block": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", - "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", - "dev": true, - "dependencies": { - "async": "^2.0.1", - "ethereum-common": "0.2.0", - "ethereumjs-tx": "^1.2.2", - "ethereumjs-util": "^5.0.0", - "merkle-patricia-tree": "^2.1.2" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-block/node_modules/ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-tx": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", - "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", - "dev": true, - "dependencies": { - "ethereum-common": "^0.0.18", - "ethereumjs-util": "^5.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz", - "integrity": "sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==", - "dev": true, - "dependencies": { - "async": "^2.1.2", - "async-eventemitter": "^0.2.2", - "ethereumjs-account": "^2.0.3", - "ethereumjs-block": "~2.2.0", - "ethereumjs-common": "^1.1.0", - "ethereumjs-util": "^6.0.0", - "fake-merkle-patricia-tree": "^1.0.1", - "functional-red-black-tree": "^1.0.1", - "merkle-patricia-tree": "^2.3.2", - "rustbn.js": "~0.2.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm/node_modules/ethereumjs-block": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", - "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", - "dev": true, - "dependencies": { - "async": "^2.0.1", - "ethereumjs-common": "^1.5.0", - "ethereumjs-tx": "^2.1.1", - "ethereumjs-util": "^5.0.0", - "merkle-patricia-tree": "^2.1.2" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm/node_modules/ethereumjs-block/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm/node_modules/ethereumjs-tx": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", - "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", - "dev": true, - "dependencies": { - "ethereumjs-common": "^1.5.0", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ethereumjs-vm/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-codec": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", - "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-errors": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", - "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", - "dev": true, - "dependencies": { - "errno": "~0.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-iterator-stream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", - "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "level-errors": "^1.0.3", - "readable-stream": "^1.0.33", - "xtend": "^4.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-iterator-stream/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-ws": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", - "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", - "dev": true, - "dependencies": { - "readable-stream": "~1.0.15", - "xtend": "~2.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-ws/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/level-ws/node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/levelup": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", - "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", - "dev": true, - "dependencies": { - "deferred-leveldown": "~1.2.1", - "level-codec": "~7.0.0", - "level-errors": "~1.0.3", - "level-iterator-stream": "~1.3.0", - "prr": "~1.0.1", - "semver": "~5.4.1", - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/ltgt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/memdown": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", - "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", - "dev": true, - "dependencies": { - "abstract-leveldown": "~2.7.1", - "functional-red-black-tree": "^1.0.1", - "immediate": "^3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.1.1" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/memdown/node_modules/abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/merkle-patricia-tree": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", - "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", - "dev": true, - "dependencies": { - "async": "^1.4.2", - "ethereumjs-util": "^5.0.0", - "level-ws": "0.0.0", - "levelup": "^1.2.1", - "memdown": "^1.0.0", - "readable-stream": "^2.0.0", - "rlp": "^2.0.0", - "semaphore": ">=1.0.1" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/merkle-patricia-tree/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ganache-core/node_modules/eth-tx-summary/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethashjs": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ethashjs/-/ethashjs-0.0.8.tgz", - "integrity": "sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw==", - "dev": true, - "dependencies": { - "async": "^2.1.2", - "buffer-xor": "^2.0.1", - "ethereumjs-util": "^7.0.2", - "miller-rabin": "^4.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethashjs/node_modules/bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethashjs/node_modules/buffer-xor": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", - "integrity": "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/ethashjs/node_modules/ethereumjs-util": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.6.tgz", - "integrity": "sha512-E9aJ9W7XZkcBqIblfstBU+0nGSjF9Dz/Ps7s1NTFOgDZM8pwD+nX1P1GBJeSqB6Osxhj2UtuxVCqjvmrj2svzw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^5.1.2", - "create-hash": "^1.1.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethereum-bloom-filters": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.7.tgz", - "integrity": "sha512-cDcJJSJ9GMAcURiAWO3DxIEhTL/uWqlQnvgKpuYQzYPrt/izuGU+1ntQmHt0IRq6ADoSYHFnB+aCEFIldjhkMQ==", - "dev": true, - "optional": true, - "dependencies": { - "js-sha3": "^0.8.0" - } - }, - "node_modules/ganache-core/node_modules/ethereum-bloom-filters/node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/ethereum-common": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-abi": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", - "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-account": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz", - "integrity": "sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA==", - "dev": true, - "dependencies": { - "ethereumjs-util": "^6.0.0", - "rlp": "^2.2.1", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", - "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", - "dev": true, - "dependencies": { - "async": "^2.0.1", - "ethereumjs-common": "^1.5.0", - "ethereumjs-tx": "^2.1.1", - "ethereumjs-util": "^5.0.0", - "merkle-patricia-tree": "^2.1.2" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/abstract-leveldown": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", - "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/deferred-leveldown": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", - "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", - "dev": true, - "dependencies": { - "abstract-leveldown": "~2.6.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-codec": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", - "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-errors": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", - "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", - "dev": true, - "dependencies": { - "errno": "~0.1.1" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-iterator-stream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", - "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "level-errors": "^1.0.3", - "readable-stream": "^1.0.33", - "xtend": "^4.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-iterator-stream/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-ws": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", - "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", - "dev": true, - "dependencies": { - "readable-stream": "~1.0.15", - "xtend": "~2.1.1" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-ws/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/level-ws/node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/levelup": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", - "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", - "dev": true, - "dependencies": { - "deferred-leveldown": "~1.2.1", - "level-codec": "~7.0.0", - "level-errors": "~1.0.3", - "level-iterator-stream": "~1.3.0", - "prr": "~1.0.1", - "semver": "~5.4.1", - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/ltgt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/memdown": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", - "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", - "dev": true, - "dependencies": { - "abstract-leveldown": "~2.7.1", - "functional-red-black-tree": "^1.0.1", - "immediate": "^3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.1.1" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/memdown/node_modules/abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/merkle-patricia-tree": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", - "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", - "dev": true, - "dependencies": { - "async": "^1.4.2", - "ethereumjs-util": "^5.0.0", - "level-ws": "0.0.0", - "levelup": "^1.2.1", - "memdown": "^1.0.0", - "readable-stream": "^2.0.0", - "rlp": "^2.0.0", - "semaphore": ">=1.0.1" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/merkle-patricia-tree/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-block/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-blockchain": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz", - "integrity": "sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ==", - "dev": true, - "dependencies": { - "async": "^2.6.1", - "ethashjs": "~0.0.7", - "ethereumjs-block": "~2.2.2", - "ethereumjs-common": "^1.5.0", - "ethereumjs-util": "^6.1.0", - "flow-stoplight": "^1.0.0", - "level-mem": "^3.0.1", - "lru-cache": "^5.1.1", - "rlp": "^2.2.2", - "semaphore": "^1.1.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-common": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz", - "integrity": "sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-tx": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", - "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", - "dev": true, - "dependencies": { - "ethereumjs-common": "^1.5.0", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz", - "integrity": "sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA==", - "dev": true, - "dependencies": { - "async": "^2.1.2", - "async-eventemitter": "^0.2.2", - "core-js-pure": "^3.0.1", - "ethereumjs-account": "^3.0.0", - "ethereumjs-block": "^2.2.2", - "ethereumjs-blockchain": "^4.0.3", - "ethereumjs-common": "^1.5.0", - "ethereumjs-tx": "^2.1.2", - "ethereumjs-util": "^6.2.0", - "fake-merkle-patricia-tree": "^1.0.1", - "functional-red-black-tree": "^1.0.1", - "merkle-patricia-tree": "^2.3.2", - "rustbn.js": "~0.2.0", - "safe-buffer": "^5.1.1", - "util.promisify": "^1.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/abstract-leveldown": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", - "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/deferred-leveldown": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", - "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", - "dev": true, - "dependencies": { - "abstract-leveldown": "~2.6.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-codec": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", - "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-errors": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", - "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", - "dev": true, - "dependencies": { - "errno": "~0.1.1" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-iterator-stream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", - "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "level-errors": "^1.0.3", - "readable-stream": "^1.0.33", - "xtend": "^4.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-iterator-stream/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-ws": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", - "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", - "dev": true, - "dependencies": { - "readable-stream": "~1.0.15", - "xtend": "~2.1.1" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-ws/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/level-ws/node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/levelup": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", - "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", - "dev": true, - "dependencies": { - "deferred-leveldown": "~1.2.1", - "level-codec": "~7.0.0", - "level-errors": "~1.0.3", - "level-iterator-stream": "~1.3.0", - "prr": "~1.0.1", - "semver": "~5.4.1", - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/ltgt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/memdown": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", - "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", - "dev": true, - "dependencies": { - "abstract-leveldown": "~2.7.1", - "functional-red-black-tree": "^1.0.1", - "immediate": "^3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.1.1" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/memdown/node_modules/abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/merkle-patricia-tree": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", - "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", - "dev": true, - "dependencies": { - "async": "^1.4.2", - "ethereumjs-util": "^5.0.0", - "level-ws": "0.0.0", - "levelup": "^1.2.1", - "memdown": "^1.0.0", - "readable-stream": "^2.0.0", - "rlp": "^2.0.0", - "semaphore": ">=1.0.1" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/merkle-patricia-tree/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ganache-core/node_modules/ethereumjs-vm/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ethereumjs-wallet": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz", - "integrity": "sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA==", - "dev": true, - "optional": true, - "dependencies": { - "aes-js": "^3.1.1", - "bs58check": "^2.1.2", - "ethereum-cryptography": "^0.1.3", - "ethereumjs-util": "^6.0.0", - "randombytes": "^2.0.6", - "safe-buffer": "^5.1.2", - "scryptsy": "^1.2.1", - "utf8": "^3.0.0", - "uuid": "^3.3.2" - } - }, - "node_modules/ganache-core/node_modules/ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ganache-core/node_modules/ethjs-unit/node_modules/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ganache-core/node_modules/eventemitter3": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", - "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/events": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", - "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/ganache-core/node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/ganache-core/node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/expand-brackets/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/expand-brackets/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/ganache-core/node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dev": true, - "optional": true, - "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/ganache-core/node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "optional": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/ganache-core/node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/express/node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/ganache-core/node_modules/express/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "dependencies": { - "type": "^2.0.0" - } - }, - "node_modules/ganache-core/node_modules/ext/node_modules/type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", - "dev": true - }, - "node_modules/ganache-core/node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/ganache-core/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/extglob/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/ganache-core/node_modules/fake-merkle-patricia-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz", - "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", - "dev": true, - "dependencies": { - "checkpoint-store": "^1.1.0" - } - }, - "node_modules/ganache-core/node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/ganache-core/node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/ganache-core/node_modules/fetch-ponyfill": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz", - "integrity": "sha1-rjzl9zLGReq4fkroeTQUcJsjmJM=", - "dev": true, - "dependencies": { - "node-fetch": "~1.7.1" - } - }, - "node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "dev": true, - "dependencies": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } - }, - "node_modules/ganache-core/node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "optional": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ganache-core/node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "optional": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/ganache-core/node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/find-yarn-workspace-root": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz", - "integrity": "sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==", - "dev": true, - "dependencies": { - "fs-extra": "^4.0.3", - "micromatch": "^3.1.4" - } - }, - "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/find-yarn-workspace-root/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/flow-stoplight": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz", - "integrity": "sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s=", - "dev": true - }, - "node_modules/ganache-core/node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/ganache-core/node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ganache-core/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/ganache-core/node_modules/forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/ganache-core/node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/ganache-core/node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/ganache-core/node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/ganache-core/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "optional": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ganache-core/node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/ganache-core/node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ganache-core/node_modules/global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "dev": true, - "dependencies": { - "min-document": "^2.19.0", - "process": "~0.5.1" - } - }, - "node_modules/ganache-core/node_modules/global/node_modules/process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/ganache-core/node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "optional": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/ganache-core/node_modules/got/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "optional": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "node_modules/ganache-core/node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/ganache-core/node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", - "dev": true, - "optional": true, - "engines": { - "node": "*" - } - }, - "node_modules/ganache-core/node_modules/has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, - "optional": true, - "dependencies": { - "has-symbol-support-x": "^1.4.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ganache-core/node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/has-values/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/ganache-core/node_modules/has-values/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/has-values/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/hash-base/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ganache-core/node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/ganache-core/node_modules/heap": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", - "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=", - "dev": true - }, - "node_modules/ganache-core/node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/ganache-core/node_modules/home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "optional": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/http-errors/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/http-https": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", - "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/ganache-core/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/idna-uts46-hx": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", - "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", - "dev": true, - "optional": true, - "dependencies": { - "punycode": "2.1.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/ganache-core/node_modules/idna-uts46-hx/node_modules/punycode": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", - "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "node_modules/ganache-core/node_modules/immediate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", - "dev": true - }, - "node_modules/ganache-core/node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/ganache-core/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/ganache-core/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ganache-core/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/ganache-core/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/is-fn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fn/-/is-fn-1.0.0.tgz", - "integrity": "sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", - "dev": true, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ganache-core/node_modules/is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/is-retry-allowed": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/ganache-core/node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/ganache-core/node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/ganache-core/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "node_modules/ganache-core/node_modules/isurl": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, - "optional": true, - "dependencies": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/ganache-core/node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "node_modules/ganache-core/node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/json-rpc-engine": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz", - "integrity": "sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA==", - "dev": true, - "dependencies": { - "async": "^2.0.1", - "babel-preset-env": "^1.7.0", - "babelify": "^7.3.0", - "json-rpc-error": "^2.0.0", - "promise-to-callback": "^1.0.0", - "safe-event-emitter": "^1.0.1" - } - }, - "node_modules/ganache-core/node_modules/json-rpc-error": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/json-rpc-error/-/json-rpc-error-2.0.0.tgz", - "integrity": "sha1-p6+cICg4tekFxyUOVH8a/3cligI=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1" - } - }, - "node_modules/ganache-core/node_modules/json-rpc-random-id": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz", - "integrity": "sha1-uknZat7RRE27jaPSA3SKy7zeyMg=", - "dev": true - }, - "node_modules/ganache-core/node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "node_modules/ganache-core/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/ganache-core/node_modules/json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "dependencies": { - "jsonify": "~0.0.0" - } - }, - "node_modules/ganache-core/node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "node_modules/ganache-core/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/ganache-core/node_modules/jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "node_modules/ganache-core/node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "node_modules/ganache-core/node_modules/keccak": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", - "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ganache-core/node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "optional": true, - "dependencies": { - "json-buffer": "3.0.0" - } - }, - "node_modules/ganache-core/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/klaw-sync": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", - "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11" - } - }, - "node_modules/ganache-core/node_modules/level-codec": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", - "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", - "dev": true, - "dependencies": { - "buffer": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/level-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", - "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", - "dev": true, - "dependencies": { - "errno": "~0.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/level-iterator-stream": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz", - "integrity": "sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.5", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/level-mem": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-3.0.1.tgz", - "integrity": "sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg==", - "dev": true, - "dependencies": { - "level-packager": "~4.0.0", - "memdown": "~3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/level-mem/node_modules/abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/level-mem/node_modules/ltgt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", - "dev": true - }, - "node_modules/ganache-core/node_modules/level-mem/node_modules/memdown": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz", - "integrity": "sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA==", - "dev": true, - "dependencies": { - "abstract-leveldown": "~5.0.0", - "functional-red-black-tree": "~1.0.1", - "immediate": "~3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/level-mem/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ganache-core/node_modules/level-packager": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-4.0.1.tgz", - "integrity": "sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q==", - "dev": true, - "dependencies": { - "encoding-down": "~5.0.0", - "levelup": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/level-post": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/level-post/-/level-post-1.0.7.tgz", - "integrity": "sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew==", - "dev": true, - "dependencies": { - "ltgt": "^2.1.2" - } - }, - "node_modules/ganache-core/node_modules/level-sublevel": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/level-sublevel/-/level-sublevel-6.6.4.tgz", - "integrity": "sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA==", - "dev": true, - "dependencies": { - "bytewise": "~1.1.0", - "level-codec": "^9.0.0", - "level-errors": "^2.0.0", - "level-iterator-stream": "^2.0.3", - "ltgt": "~2.1.1", - "pull-defer": "^0.2.2", - "pull-level": "^2.0.3", - "pull-stream": "^3.6.8", - "typewiselite": "~1.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/level-ws": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-1.0.0.tgz", - "integrity": "sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.2.8", - "xtend": "^4.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/levelup": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz", - "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==", - "dev": true, - "dependencies": { - "deferred-leveldown": "~4.0.0", - "level-errors": "~2.0.0", - "level-iterator-stream": "~3.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/levelup/node_modules/level-iterator-stream": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", - "integrity": "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, - "node_modules/ganache-core/node_modules/looper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/looper/-/looper-2.0.0.tgz", - "integrity": "sha1-Zs0Md0rz1P7axTeU90LbVtqPCew=", - "dev": true - }, - "node_modules/ganache-core/node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/ganache-core/node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/ganache-core/node_modules/ltgt": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.1.3.tgz", - "integrity": "sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ=", - "dev": true - }, - "node_modules/ganache-core/node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/ganache-core/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/merkle-patricia-tree": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz", - "integrity": "sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ==", - "dev": true, - "dependencies": { - "async": "^2.6.1", - "ethereumjs-util": "^5.2.0", - "level-mem": "^3.0.1", - "level-ws": "^1.0.0", - "readable-stream": "^3.0.6", - "rlp": "^2.0.0", - "semaphore": ">=1.0.1" - } - }, - "node_modules/ganache-core/node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/merkle-patricia-tree/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ganache-core/node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/ganache-core/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "optional": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, - "dependencies": { - "mime-db": "1.44.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "dev": true, - "dependencies": { - "dom-walk": "^0.1.0" - } - }, - "node_modules/ganache-core/node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/ganache-core/node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "node_modules/ganache-core/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ganache-core/node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "node_modules/ganache-core/node_modules/minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dev": true, - "optional": true, - "dependencies": { - "minipass": "^2.9.0" - } - }, - "node_modules/ganache-core/node_modules/minizlib/node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/ganache-core/node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ganache-core/node_modules/mkdirp-promise": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", - "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", - "dev": true, - "optional": true, - "dependencies": { - "mkdirp": "*" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/mock-fs": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.13.0.tgz", - "integrity": "sha512-DD0vOdofJdoaRNtnWcrXe6RQbpHkPPmtqGq14uRX0F8ZKJ5nv89CVTYl/BZdppDxBDaV0hl75htg3abpEWlPZA==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/ganache-core/node_modules/multibase": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", - "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", - "dev": true, - "optional": true, - "dependencies": { - "base-x": "^3.0.8", - "buffer": "^5.5.0" - } - }, - "node_modules/ganache-core/node_modules/multicodec": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", - "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", - "dev": true, - "optional": true, - "dependencies": { - "varint": "^5.0.0" - } - }, - "node_modules/ganache-core/node_modules/multihashes": { - "version": "0.4.21", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", - "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", - "dev": true, - "optional": true, - "dependencies": { - "buffer": "^5.5.0", - "multibase": "^0.7.0", - "varint": "^5.0.0" - } - }, - "node_modules/ganache-core/node_modules/multihashes/node_modules/multibase": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", - "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", - "dev": true, - "optional": true, - "dependencies": { - "base-x": "^3.0.8", - "buffer": "^5.5.0" - } - }, - "node_modules/ganache-core/node_modules/nano-json-stream-parser": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", - "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node_modules/ganache-core/node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "dev": true - }, - "node_modules/ganache-core/node_modules/node-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", - "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", - "dev": true, - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/ganache-core/node_modules/node-gyp-build": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", - "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", - "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/ganache-core/node_modules/normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ganache-core/node_modules/number-to-bn": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", - "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "4.11.6", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ganache-core/node_modules/number-to-bn/node_modules/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ganache-core/node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/object-copy/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/object-copy/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/ganache-core/node_modules/object-copy/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/object-copy/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "node_modules/ganache-core/node_modules/object-is": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", - "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/object-is/node_modules/es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/object.assign/node_modules/es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ganache-core/node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/oboe": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.4.tgz", - "integrity": "sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY=", - "dev": true, - "optional": true, - "dependencies": { - "http-https": "^1.0.0" - } - }, - "node_modules/ganache-core/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "optional": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ganache-core/node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/ganache-core/node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/p-timeout": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", - "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", - "dev": true, - "optional": true, - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/p-timeout/node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "optional": true, - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/parse-headers": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", - "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==", - "dev": true - }, - "node_modules/ganache-core/node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ganache-core/node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/patch-package": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.2.2.tgz", - "integrity": "sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg==", - "dev": true, - "dependencies": { - "@yarnpkg/lockfile": "^1.1.0", - "chalk": "^2.4.2", - "cross-spawn": "^6.0.5", - "find-yarn-workspace-root": "^1.2.1", - "fs-extra": "^7.0.1", - "is-ci": "^2.0.0", - "klaw-sync": "^6.0.0", - "minimist": "^1.2.0", - "rimraf": "^2.6.3", - "semver": "^5.6.0", - "slash": "^2.0.0", - "tmp": "^0.0.33" - }, - "bin": { - "patch-package": "index.js" - }, - "engines": { - "npm": ">5" - } - }, - "node_modules/ganache-core/node_modules/patch-package/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/ganache-core/node_modules/patch-package/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/patch-package/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ganache-core/node_modules/patch-package/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/patch-package/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/patch-package/node_modules/slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/patch-package/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/ganache-core/node_modules/patch-package/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/ganache-core/node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "node_modules/ganache-core/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", - "dev": true, - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/ganache-core/node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "node_modules/ganache-core/node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/precond": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", - "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/ganache-core/node_modules/promise-to-callback": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/promise-to-callback/-/promise-to-callback-1.0.0.tgz", - "integrity": "sha1-XSp0kBC/tn2WNZj805YHRqaP7vc=", - "dev": true, - "dependencies": { - "is-fn": "^1.0.0", - "set-immediate-shim": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "dev": true, - "optional": true, - "dependencies": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ganache-core/node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "node_modules/ganache-core/node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "node_modules/ganache-core/node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/ganache-core/node_modules/pull-cat": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/pull-cat/-/pull-cat-1.1.11.tgz", - "integrity": "sha1-tkLdElXaN2pwa220+pYvX9t0wxs=", - "dev": true - }, - "node_modules/ganache-core/node_modules/pull-defer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/pull-defer/-/pull-defer-0.2.3.tgz", - "integrity": "sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA==", - "dev": true - }, - "node_modules/ganache-core/node_modules/pull-level": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pull-level/-/pull-level-2.0.4.tgz", - "integrity": "sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg==", - "dev": true, - "dependencies": { - "level-post": "^1.0.7", - "pull-cat": "^1.1.9", - "pull-live": "^1.0.1", - "pull-pushable": "^2.0.0", - "pull-stream": "^3.4.0", - "pull-window": "^2.1.4", - "stream-to-pull-stream": "^1.7.1" - } - }, - "node_modules/ganache-core/node_modules/pull-live": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pull-live/-/pull-live-1.0.1.tgz", - "integrity": "sha1-pOzuAeMwFV6RJLu89HYfIbOPUfU=", - "dev": true, - "dependencies": { - "pull-cat": "^1.1.9", - "pull-stream": "^3.4.0" - } - }, - "node_modules/ganache-core/node_modules/pull-pushable": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pull-pushable/-/pull-pushable-2.2.0.tgz", - "integrity": "sha1-Xy867UethpGfAbEqLpnW8b13ZYE=", - "dev": true - }, - "node_modules/ganache-core/node_modules/pull-stream": { - "version": "3.6.14", - "resolved": "https://registry.npmjs.org/pull-stream/-/pull-stream-3.6.14.tgz", - "integrity": "sha512-KIqdvpqHHaTUA2mCYcLG1ibEbu/LCKoJZsBWyv9lSYtPkJPBq8m3Hxa103xHi6D2thj5YXa0TqK3L3GUkwgnew==", - "dev": true - }, - "node_modules/ganache-core/node_modules/pull-window": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/pull-window/-/pull-window-2.1.4.tgz", - "integrity": "sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA=", - "dev": true, - "dependencies": { - "looper": "^2.0.0" - } - }, - "node_modules/ganache-core/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "optional": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/ganache-core/node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/ganache-core/node_modules/query-string": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, - "optional": true, - "dependencies": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/ganache-core/node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "optional": true, - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "node_modules/ganache-core/node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "optional": true, - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ganache-core/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/ganache-core/node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ganache-core/node_modules/regenerate": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", - "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", - "dev": true - }, - "node_modules/ganache-core/node_modules/regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, - "node_modules/ganache-core/node_modules/regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, - "dependencies": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" - } - }, - "node_modules/ganache-core/node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "dependencies": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - }, - "node_modules/ganache-core/node_modules/regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "node_modules/ganache-core/node_modules/regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/ganache-core/node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/ganache-core/node_modules/repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/ganache-core/node_modules/repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "dependencies": { - "is-finite": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ganache-core/node_modules/resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "dependencies": { - "path-parse": "^1.0.6" - } - }, - "node_modules/ganache-core/node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "node_modules/ganache-core/node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "optional": true, - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, - "node_modules/ganache-core/node_modules/resumer": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", - "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", - "dev": true, - "dependencies": { - "through": "~2.3.4" - } - }, - "node_modules/ganache-core/node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/ganache-core/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/ganache-core/node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/ganache-core/node_modules/rlp": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", - "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.1" - }, - "bin": { - "rlp": "bin/rlp" - } - }, - "node_modules/ganache-core/node_modules/rustbn.js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", - "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", - "dev": true - }, - "node_modules/ganache-core/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/safe-event-emitter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz", - "integrity": "sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg==", - "dev": true, - "dependencies": { - "events": "^3.0.0" - } - }, - "node_modules/ganache-core/node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/ganache-core/node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/ganache-core/node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "dev": true - }, - "node_modules/ganache-core/node_modules/scryptsy": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", - "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", - "dev": true, - "optional": true, - "dependencies": { - "pbkdf2": "^3.0.3" - } - }, - "node_modules/ganache-core/node_modules/secp256k1": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", - "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "elliptic": "^6.5.2", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ganache-core/node_modules/seedrandom": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.1.tgz", - "integrity": "sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg==", - "dev": true - }, - "node_modules/ganache-core/node_modules/semaphore": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", - "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/ganache-core/node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "optional": true, - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ganache-core/node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "optional": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/ganache-core/node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "optional": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ganache-core/node_modules/servify": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", - "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", - "dev": true, - "optional": true, - "dependencies": { - "body-parser": "^1.16.0", - "cors": "^2.8.1", - "express": "^4.14.0", - "request": "^2.79.0", - "xhr": "^2.3.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/set-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/ganache-core/node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/ganache-core/node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/simple-get": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", - "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", - "dev": true, - "optional": true, - "dependencies": { - "decompress-response": "^3.3.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon-util/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/ganache-core/node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/ganache-core/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/ganache-core/node_modules/source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/ganache-core/node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "node_modules/ganache-core/node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/sshpk/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "node_modules/ganache-core/node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/static-extend/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/static-extend/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/ganache-core/node_modules/static-extend/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/static-extend/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/static-extend/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/stream-to-pull-stream": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz", - "integrity": "sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg==", - "dev": true, - "dependencies": { - "looper": "^3.0.0", - "pull-stream": "^3.2.3" - } - }, - "node_modules/ganache-core/node_modules/stream-to-pull-stream/node_modules/looper": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/looper/-/looper-3.0.0.tgz", - "integrity": "sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k=", - "dev": true - }, - "node_modules/ganache-core/node_modules/strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/ganache-core/node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ganache-core/node_modules/string.prototype.trim": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.2.tgz", - "integrity": "sha512-b5yrbl3BXIjHau9Prk7U0RRYcUYdN4wGSVaqoBQS50CCE3KBuYU0TYRNPFCP7aVoNMX87HKThdMRVIP3giclKg==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/string.prototype.trim/node_modules/es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/ganache-core/node_modules/string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/ganache-core/node_modules/strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ganache-core/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/swarm-js": { - "version": "0.1.40", - "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.40.tgz", - "integrity": "sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA==", - "dev": true, - "optional": true, - "dependencies": { - "bluebird": "^3.5.0", - "buffer": "^5.0.5", - "eth-lib": "^0.1.26", - "fs-extra": "^4.0.2", - "got": "^7.1.0", - "mime-types": "^2.1.16", - "mkdirp-promise": "^5.0.1", - "mock-fs": "^4.1.0", - "setimmediate": "^1.0.5", - "tar": "^4.0.2", - "xhr-request": "^1.0.1" - } - }, - "node_modules/ganache-core/node_modules/swarm-js/node_modules/fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dev": true, - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "node_modules/ganache-core/node_modules/swarm-js/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/swarm-js/node_modules/got": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", - "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", - "dev": true, - "optional": true, - "dependencies": { - "decompress-response": "^3.2.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-plain-obj": "^1.1.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "p-cancelable": "^0.3.0", - "p-timeout": "^1.1.1", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "url-parse-lax": "^1.0.0", - "url-to-options": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/swarm-js/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/swarm-js/node_modules/p-cancelable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/swarm-js/node_modules/prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/swarm-js/node_modules/url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "optional": true, - "dependencies": { - "prepend-http": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/tape": { - "version": "4.13.3", - "resolved": "https://registry.npmjs.org/tape/-/tape-4.13.3.tgz", - "integrity": "sha512-0/Y20PwRIUkQcTCSi4AASs+OANZZwqPKaipGCEwp10dQMipVvSZwUUCi01Y/OklIGyHKFhIcjock+DKnBfLAFw==", - "dev": true, - "dependencies": { - "deep-equal": "~1.1.1", - "defined": "~1.0.0", - "dotignore": "~0.1.2", - "for-each": "~0.3.3", - "function-bind": "~1.1.1", - "glob": "~7.1.6", - "has": "~1.0.3", - "inherits": "~2.0.4", - "is-regex": "~1.0.5", - "minimist": "~1.2.5", - "object-inspect": "~1.7.0", - "resolve": "~1.17.0", - "resumer": "~0.0.0", - "string.prototype.trim": "~1.2.1", - "through": "~2.3.8" - }, - "bin": { - "tape": "bin/tape" - } - }, - "node_modules/ganache-core/node_modules/tape/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ganache-core/node_modules/tape/node_modules/is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ganache-core/node_modules/tape/node_modules/object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true - }, - "node_modules/ganache-core/node_modules/tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "dev": true, - "optional": true, - "dependencies": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - }, - "engines": { - "node": ">=4.5" - } - }, - "node_modules/ganache-core/node_modules/tar/node_modules/fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "optional": true, - "dependencies": { - "minipass": "^2.6.0" - } - }, - "node_modules/ganache-core/node_modules/tar/node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/ganache-core/node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/ganache-core/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/ganache-core/node_modules/timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/tmp": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", - "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", - "dev": true, - "dependencies": { - "rimraf": "^2.6.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/to-object-path/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/ganache-core/node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-core/node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/ganache-core/node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/ganache-core/node_modules/trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ganache-core/node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true - }, - "node_modules/ganache-core/node_modules/tweetnacl-util": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", - "dev": true - }, - "node_modules/ganache-core/node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/ganache-core/node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "optional": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ganache-core/node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/ganache-core/node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/ganache-core/node_modules/typewise": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz", - "integrity": "sha1-EGeTZUCvl5N8xdz5kiSG6fooRlE=", - "dev": true, - "dependencies": { - "typewise-core": "^1.2.0" - } - }, - "node_modules/ganache-core/node_modules/typewise-core": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz", - "integrity": "sha1-l+uRgFx/VdL5QXSPpQ0xXZke8ZU=", - "dev": true - }, - "node_modules/ganache-core/node_modules/typewiselite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typewiselite/-/typewiselite-1.0.0.tgz", - "integrity": "sha1-yIgvobsQksBgBal/NO9chQjjZk4=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/underscore": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", - "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/union-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/ganache-core/node_modules/unorm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", - "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/ganache-core/node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ganache-core/node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/ganache-core/node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "node_modules/ganache-core/node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, - "optional": true, - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-core/node_modules/url-set-query": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", - "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/url-to-options": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/ganache-core/node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-core/node_modules/utf-8-validate": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz", - "integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-gyp-build": "~3.7.0" - } - }, - "node_modules/ganache-core/node_modules/utf-8-validate/node_modules/node-gyp-build": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", - "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", - "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/ganache-core/node_modules/utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/ganache-core/node_modules/util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - } - }, - "node_modules/ganache-core/node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/ganache-core/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/ganache-core/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ganache-core/node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/ganache-core/node_modules/web3": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.11.tgz", - "integrity": "sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "web3-bzz": "1.2.11", - "web3-core": "1.2.11", - "web3-eth": "1.2.11", - "web3-eth-personal": "1.2.11", - "web3-net": "1.2.11", - "web3-shh": "1.2.11", - "web3-utils": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-bzz": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.11.tgz", - "integrity": "sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "^12.12.6", - "got": "9.6.0", - "swarm-js": "^0.1.40", - "underscore": "1.9.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-bzz/node_modules/@types/node": { - "version": "12.12.67", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz", - "integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/web3-core": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.11.tgz", - "integrity": "sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ==", - "dev": true, - "optional": true, - "dependencies": { - "@types/bn.js": "^4.11.5", - "@types/node": "^12.12.6", - "bignumber.js": "^9.0.0", - "web3-core-helpers": "1.2.11", - "web3-core-method": "1.2.11", - "web3-core-requestmanager": "1.2.11", - "web3-utils": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-core-helpers": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz", - "integrity": "sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A==", - "dev": true, - "optional": true, - "dependencies": { - "underscore": "1.9.1", - "web3-eth-iban": "1.2.11", - "web3-utils": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-core-method": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.11.tgz", - "integrity": "sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/transactions": "^5.0.0-beta.135", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.11", - "web3-core-promievent": "1.2.11", - "web3-core-subscriptions": "1.2.11", - "web3-utils": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-core-promievent": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz", - "integrity": "sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA==", - "dev": true, - "optional": true, - "dependencies": { - "eventemitter3": "4.0.4" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-core-requestmanager": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz", - "integrity": "sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA==", - "dev": true, - "optional": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.11", - "web3-providers-http": "1.2.11", - "web3-providers-ipc": "1.2.11", - "web3-providers-ws": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-core-subscriptions": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz", - "integrity": "sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg==", - "dev": true, - "optional": true, - "dependencies": { - "eventemitter3": "4.0.4", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-core/node_modules/@types/node": { - "version": "12.12.67", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz", - "integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/web3-eth": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.11.tgz", - "integrity": "sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ==", - "dev": true, - "optional": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core": "1.2.11", - "web3-core-helpers": "1.2.11", - "web3-core-method": "1.2.11", - "web3-core-subscriptions": "1.2.11", - "web3-eth-abi": "1.2.11", - "web3-eth-accounts": "1.2.11", - "web3-eth-contract": "1.2.11", - "web3-eth-ens": "1.2.11", - "web3-eth-iban": "1.2.11", - "web3-eth-personal": "1.2.11", - "web3-net": "1.2.11", - "web3-utils": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-eth-abi": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz", - "integrity": "sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/abi": "5.0.0-beta.153", - "underscore": "1.9.1", - "web3-utils": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-eth-accounts": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz", - "integrity": "sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw==", - "dev": true, - "optional": true, - "dependencies": { - "crypto-browserify": "3.12.0", - "eth-lib": "0.2.8", - "ethereumjs-common": "^1.3.2", - "ethereumjs-tx": "^2.1.1", - "scrypt-js": "^3.0.1", - "underscore": "1.9.1", - "uuid": "3.3.2", - "web3-core": "1.2.11", - "web3-core-helpers": "1.2.11", - "web3-core-method": "1.2.11", - "web3-utils": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-eth-accounts/node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/ganache-core/node_modules/web3-eth-accounts/node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true, - "optional": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/ganache-core/node_modules/web3-eth-contract": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz", - "integrity": "sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow==", - "dev": true, - "optional": true, - "dependencies": { - "@types/bn.js": "^4.11.5", - "underscore": "1.9.1", - "web3-core": "1.2.11", - "web3-core-helpers": "1.2.11", - "web3-core-method": "1.2.11", - "web3-core-promievent": "1.2.11", - "web3-core-subscriptions": "1.2.11", - "web3-eth-abi": "1.2.11", - "web3-utils": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-eth-ens": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz", - "integrity": "sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA==", - "dev": true, - "optional": true, - "dependencies": { - "content-hash": "^2.5.2", - "eth-ens-namehash": "2.0.8", - "underscore": "1.9.1", - "web3-core": "1.2.11", - "web3-core-helpers": "1.2.11", - "web3-core-promievent": "1.2.11", - "web3-eth-abi": "1.2.11", - "web3-eth-contract": "1.2.11", - "web3-utils": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-eth-iban": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz", - "integrity": "sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.11.9", - "web3-utils": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-eth-personal": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz", - "integrity": "sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "^12.12.6", - "web3-core": "1.2.11", - "web3-core-helpers": "1.2.11", - "web3-core-method": "1.2.11", - "web3-net": "1.2.11", - "web3-utils": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-eth-personal/node_modules/@types/node": { - "version": "12.12.67", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz", - "integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/web3-net": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.11.tgz", - "integrity": "sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg==", - "dev": true, - "optional": true, - "dependencies": { - "web3-core": "1.2.11", - "web3-core-method": "1.2.11", - "web3-utils": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz", - "integrity": "sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw==", - "dev": true, - "dependencies": { - "async": "^2.5.0", - "backoff": "^2.5.0", - "clone": "^2.0.0", - "cross-fetch": "^2.1.0", - "eth-block-tracker": "^3.0.0", - "eth-json-rpc-infura": "^3.1.0", - "eth-sig-util": "^1.4.2", - "ethereumjs-block": "^1.2.2", - "ethereumjs-tx": "^1.2.0", - "ethereumjs-util": "^5.1.5", - "ethereumjs-vm": "^2.3.4", - "json-rpc-error": "^2.0.0", - "json-stable-stringify": "^1.0.1", - "promise-to-callback": "^1.0.0", - "readable-stream": "^2.2.9", - "request": "^2.85.0", - "semaphore": "^1.0.3", - "ws": "^5.1.1", - "xhr": "^2.2.0", - "xtend": "^4.0.1" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/abstract-leveldown": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", - "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/deferred-leveldown": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", - "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", - "dev": true, - "dependencies": { - "abstract-leveldown": "~2.6.0" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/eth-sig-util": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz", - "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", - "dev": true, - "dependencies": { - "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git", - "ethereumjs-util": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-abi": { - "resolved": "git+https://git@github.com/ethereumjs/ethereumjs-abi.git#1ce6a1d64235fabe2aaf827fd606def55693508f", - "dev": true, - "dependencies": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-account": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", - "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", - "dev": true, - "dependencies": { - "ethereumjs-util": "^5.0.0", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-block": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", - "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", - "dev": true, - "dependencies": { - "async": "^2.0.1", - "ethereum-common": "0.2.0", - "ethereumjs-tx": "^1.2.2", - "ethereumjs-util": "^5.0.0", - "merkle-patricia-tree": "^2.1.2" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-block/node_modules/ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-tx": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", - "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", - "dev": true, - "dependencies": { - "ethereum-common": "^0.0.18", - "ethereumjs-util": "^5.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz", - "integrity": "sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==", - "dev": true, - "dependencies": { - "async": "^2.1.2", - "async-eventemitter": "^0.2.2", - "ethereumjs-account": "^2.0.3", - "ethereumjs-block": "~2.2.0", - "ethereumjs-common": "^1.1.0", - "ethereumjs-util": "^6.0.0", - "fake-merkle-patricia-tree": "^1.0.1", - "functional-red-black-tree": "^1.0.1", - "merkle-patricia-tree": "^2.3.2", - "rustbn.js": "~0.2.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm/node_modules/ethereumjs-block": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", - "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", - "dev": true, - "dependencies": { - "async": "^2.0.1", - "ethereumjs-common": "^1.5.0", - "ethereumjs-tx": "^2.1.1", - "ethereumjs-util": "^5.0.0", - "merkle-patricia-tree": "^2.1.2" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm/node_modules/ethereumjs-block/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm/node_modules/ethereumjs-tx": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", - "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", - "dev": true, - "dependencies": { - "ethereumjs-common": "^1.5.0", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ethereumjs-vm/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-codec": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", - "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", - "dev": true - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-errors": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", - "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", - "dev": true, - "dependencies": { - "errno": "~0.1.1" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-iterator-stream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", - "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "level-errors": "^1.0.3", - "readable-stream": "^1.0.33", - "xtend": "^4.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-iterator-stream/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-ws": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", - "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", - "dev": true, - "dependencies": { - "readable-stream": "~1.0.15", - "xtend": "~2.1.1" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-ws/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/level-ws/node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/levelup": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", - "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", - "dev": true, - "dependencies": { - "deferred-leveldown": "~1.2.1", - "level-codec": "~7.0.0", - "level-errors": "~1.0.3", - "level-iterator-stream": "~1.3.0", - "prr": "~1.0.1", - "semver": "~5.4.1", - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ltgt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", - "dev": true - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/memdown": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", - "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", - "dev": true, - "dependencies": { - "abstract-leveldown": "~2.7.1", - "functional-red-black-tree": "^1.0.1", - "immediate": "^3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.1.1" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/memdown/node_modules/abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/merkle-patricia-tree": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", - "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", - "dev": true, - "dependencies": { - "async": "^1.4.2", - "ethereumjs-util": "^5.0.0", - "level-ws": "0.0.0", - "levelup": "^1.2.1", - "memdown": "^1.0.0", - "readable-stream": "^2.0.0", - "rlp": "^2.0.0", - "semaphore": ">=1.0.1" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/merkle-patricia-tree/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/ganache-core/node_modules/web3-provider-engine/node_modules/ws": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", - "dev": true, - "dependencies": { - "async-limiter": "~1.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-providers-http": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.11.tgz", - "integrity": "sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA==", - "dev": true, - "optional": true, - "dependencies": { - "web3-core-helpers": "1.2.11", - "xhr2-cookies": "1.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-providers-ipc": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz", - "integrity": "sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ==", - "dev": true, - "optional": true, - "dependencies": { - "oboe": "2.1.4", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-providers-ws": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz", - "integrity": "sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg==", - "dev": true, - "optional": true, - "dependencies": { - "eventemitter3": "4.0.4", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.11", - "websocket": "^1.0.31" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-shh": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.11.tgz", - "integrity": "sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg==", - "dev": true, - "optional": true, - "dependencies": { - "web3-core": "1.2.11", - "web3-core-method": "1.2.11", - "web3-core-subscriptions": "1.2.11", - "web3-net": "1.2.11" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-utils": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.11.tgz", - "integrity": "sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.11.9", - "eth-lib": "0.2.8", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ganache-core/node_modules/web3-utils/node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/ganache-core/node_modules/websocket": { - "version": "1.0.32", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.32.tgz", - "integrity": "sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q==", - "dev": true, - "dependencies": { - "bufferutil": "^4.0.1", - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "typedarray-to-buffer": "^3.1.5", - "utf-8-validate": "^5.0.2", - "yaeti": "^0.0.6" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/ganache-core/node_modules/websocket/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/ganache-core/node_modules/websocket/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/ganache-core/node_modules/whatwg-fetch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", - "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==", - "dev": true - }, - "node_modules/ganache-core/node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/ganache-core/node_modules/ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "optional": true, - "dependencies": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - }, - "node_modules/ganache-core/node_modules/ws/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "optional": true - }, - "node_modules/ganache-core/node_modules/xhr": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", - "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", - "dev": true, - "dependencies": { - "global": "~4.3.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/ganache-core/node_modules/xhr-request": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", - "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", - "dev": true, - "optional": true, - "dependencies": { - "buffer-to-arraybuffer": "^0.0.5", - "object-assign": "^4.1.1", - "query-string": "^5.0.1", - "simple-get": "^2.7.0", - "timed-out": "^4.0.1", - "url-set-query": "^1.0.0", - "xhr": "^2.0.4" - } - }, - "node_modules/ganache-core/node_modules/xhr-request-promise": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz", - "integrity": "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==", - "dev": true, - "optional": true, - "dependencies": { - "xhr-request": "^1.1.0" - } - }, - "node_modules/ganache-core/node_modules/xhr2-cookies": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", - "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", - "dev": true, - "optional": true, - "dependencies": { - "cookiejar": "^2.1.1" - } - }, - "node_modules/ganache-core/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/ganache-core/node_modules/yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", - "dev": true, - "engines": { - "node": ">=0.10.32" - } - }, - "node_modules/ganache-core/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", - "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "node_modules/get-port": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/get-proxy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", - "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", - "dev": true, - "dependencies": { - "npm-conf": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/ghost-testrpc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", - "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "node-emoji": "^1.10.0" - }, - "bin": { - "testrpc-sc": "index.js" - } - }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "dev": true, - "dependencies": { - "min-document": "^2.19.0", - "process": "~0.5.1" - } - }, - "node_modules/global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", - "dev": true, - "dependencies": { - "ini": "^1.3.4" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/globby": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", - "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/got": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", - "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.7.0", - "cacheable-request": "^2.1.1", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "into-stream": "^3.1.0", - "is-retry-allowed": "^1.1.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "mimic-response": "^1.0.0", - "p-cancelable": "^0.4.0", - "p-timeout": "^2.0.1", - "pify": "^3.0.0", - "safe-buffer": "^5.1.1", - "timed-out": "^4.0.1", - "url-parse-lax": "^3.0.0", - "url-to-options": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/hardhat": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.0.8.tgz", - "integrity": "sha512-2tDAtOfshrBzP103dx7PQrhTwv2sqjhQStZAPwkkQTic25o2EH6HYE2++LuOG98YwqSjr0WvhvdBvKl3dCSkYA==", - "dev": true, - "dependencies": { - "@nomiclabs/ethereumjs-vm": "^4.1.1", - "@sentry/node": "^5.18.1", - "@solidity-parser/parser": "^0.11.0", - "@types/bn.js": "^4.11.5", - "@types/lru-cache": "^5.1.0", - "abort-controller": "^3.0.0", - "adm-zip": "^0.4.16", - "ansi-escapes": "^4.3.0", - "chalk": "^2.4.2", - "chokidar": "^3.4.0", - "ci-info": "^2.0.0", - "debug": "^4.1.1", - "enquirer": "^2.3.0", - "env-paths": "^2.2.0", - "eth-sig-util": "^2.5.2", - "ethereum-cryptography": "^0.1.2", - "ethereumjs-abi": "^0.6.8", - "ethereumjs-account": "^3.0.0", - "ethereumjs-block": "^2.2.0", - "ethereumjs-common": "^1.5.0", - "ethereumjs-tx": "^2.1.1", - "ethereumjs-util": "^6.1.0", - "find-up": "^2.1.0", - "fp-ts": "1.19.3", - "fs-extra": "^7.0.1", - "glob": "^7.1.3", - "immutable": "^4.0.0-rc.12", - "io-ts": "1.10.4", - "lodash": "^4.17.11", - "merkle-patricia-tree": "^3.0.0", - "mocha": "^7.1.2", - "node-fetch": "^2.6.0", - "qs": "^6.7.0", - "raw-body": "^2.4.1", - "resolve": "1.17.0", - "semver": "^6.3.0", - "slash": "^3.0.0", - "solc": "0.7.3", - "source-map-support": "^0.5.13", - "stacktrace-parser": "^0.1.10", - "true-case-path": "^2.2.1", - "tsort": "0.0.1", - "uuid": "^3.3.2", - "ws": "^7.2.1" - }, - "bin": { - "hardhat": "internal/cli/cli.js" - }, - "engines": { - "node": ">=8.2.0" - } - }, - "node_modules/hardhat-gas-reporter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.1.tgz", - "integrity": "sha512-YC+SCYIkBdRtISNbisU2BwDSelUdCrIKRsJXt3M9Jw1VF5CmtSZb8VuuOc2Zl4AMcEV2jEy6ZuAksYomPiApYQ==", - "dev": true, - "dependencies": { - "eth-gas-reporter": "^0.2.19" - } - }, - "node_modules/hardhat-typechain": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/hardhat-typechain/-/hardhat-typechain-0.3.3.tgz", - "integrity": "sha512-NrqP7Zng28prV3YT0lXoo1pXtZxoNCMfiZIWkf1HXjjID42JLLfSOTsvlb0okDMpz4tJaEEkgADJO69sKZxw+Q==", - "dev": true - }, - "node_modules/hardhat/node_modules/@solidity-parser/parser": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.11.1.tgz", - "integrity": "sha512-H8BSBoKE8EubJa0ONqecA2TviT3TnHeC4NpgnAHSUiuhZoQBfPB4L2P9bs8R6AoTW10Endvh3vc+fomVMIDIYQ==", - "dev": true - }, - "node_modules/hardhat/node_modules/commander": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", - "dev": true - }, - "node_modules/hardhat/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/hardhat/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/hardhat/node_modules/resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "dependencies": { - "path-parse": "^1.0.6" - } - }, - "node_modules/hardhat/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/hardhat/node_modules/solc": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", - "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", - "dev": true, - "dependencies": { - "command-exists": "^1.2.8", - "commander": "3.0.2", - "follow-redirects": "^1.12.1", - "fs-extra": "^0.30.0", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "require-from-string": "^2.0.0", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "bin": { - "solcjs": "solcjs" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/hardhat/node_modules/solc/node_modules/fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/hardhat/node_modules/solc/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/hardhat/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, - "dependencies": { - "has-symbol-support-x": "^1.4.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/has-values/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "node_modules/http-basic": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", - "integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==", - "dev": true, - "dependencies": { - "caseless": "^0.12.0", - "concat-stream": "^1.6.2", - "http-response-object": "^3.0.1", - "parse-cache-control": "^1.0.1" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", - "dev": true - }, - "node_modules/http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-https": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", - "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=", - "dev": true - }, - "node_modules/http-response-object": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", - "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", - "dev": true, - "dependencies": { - "@types/node": "^10.0.3" - } - }, - "node_modules/http-response-object/node_modules/@types/node": { - "version": "10.17.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", - "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", - "dev": true - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/husky": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz", - "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "chalk": "^4.0.0", - "ci-info": "^2.0.0", - "compare-versions": "^3.6.0", - "cosmiconfig": "^7.0.0", - "find-versions": "^3.2.0", - "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^4.2.0", - "please-upgrade-node": "^3.2.0", - "slash": "^3.0.0", - "which-pm-runs": "^1.0.0" - }, - "bin": { - "husky-run": "bin/run.js", - "husky-upgrade": "lib/upgrader/bin.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/husky/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/husky/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/husky/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/husky/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/husky/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/husky/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/idna-uts46-hx": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", - "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", - "dev": true, - "dependencies": { - "punycode": "2.1.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/immediate": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", - "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", - "dev": true - }, - "node_modules/immutable": { - "version": "4.0.0-rc.12", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz", - "integrity": "sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A==", - "dev": true - }, - "node_modules/import-fresh": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", - "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/into-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", - "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true, - "dependencies": { - "from2": "^2.1.1", - "p-is-promise": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/io-ts": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", - "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", - "dev": true, - "dependencies": { - "fp-ts": "^1.0.0" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-core-module": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz", - "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-data-descriptor/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", - "dev": true - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", - "dev": true, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/is-installed-globally": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.2.0.tgz", - "integrity": "sha512-g3TzWCnR/eO4Q3abCwgFjOFw7uVOfxG4m8hMr/39Jcf2YvE5mHrFKqpyuraWV4zwx9XhjnVO4nY0ZI4llzl0Pg==", - "dev": true, - "dependencies": { - "global-dirs": "^0.1.1", - "is-path-inside": "^2.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-natural-number": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", - "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", - "dev": true - }, - "node_modules/is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true - }, - "node_modules/is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "dependencies": { - "path-is-inside": "^1.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, - "node_modules/is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-retry-allowed": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "dev": true - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "node_modules/isurl": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, - "dependencies": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/jest-docblock": { - "version": "21.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz", - "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==", - "dev": true - }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonschema": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz", - "integrity": "sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "node_modules/keccak": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", - "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/keyv": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", - "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.0" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.9" - } - }, - "node_modules/klaw-sync": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", - "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11" - } - }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/level-codec": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", - "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", - "dev": true - }, - "node_modules/level-errors": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", - "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", - "dev": true, - "dependencies": { - "errno": "~0.1.1" - } - }, - "node_modules/level-iterator-stream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", - "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "level-errors": "^1.0.3", - "readable-stream": "^1.0.33", - "xtend": "^4.0.0" - } - }, - "node_modules/level-iterator-stream/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/level-iterator-stream/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/level-iterator-stream/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/level-mem": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-3.0.1.tgz", - "integrity": "sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg==", - "dev": true, - "dependencies": { - "level-packager": "~4.0.0", - "memdown": "~3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-mem/node_modules/abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-mem/node_modules/immediate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", - "dev": true - }, - "node_modules/level-mem/node_modules/memdown": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz", - "integrity": "sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA==", - "dev": true, - "dependencies": { - "abstract-leveldown": "~5.0.0", - "functional-red-black-tree": "~1.0.1", - "immediate": "~3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-mem/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/level-mem/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/level-packager": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-4.0.1.tgz", - "integrity": "sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q==", - "dev": true, - "dependencies": { - "encoding-down": "~5.0.0", - "levelup": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-packager/node_modules/abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-packager/node_modules/deferred-leveldown": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", - "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", - "dev": true, - "dependencies": { - "abstract-leveldown": "~5.0.0", - "inherits": "^2.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-packager/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/level-packager/node_modules/level-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", - "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", - "dev": true, - "dependencies": { - "errno": "~0.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-packager/node_modules/level-iterator-stream": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", - "integrity": "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-packager/node_modules/levelup": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz", - "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==", - "dev": true, - "dependencies": { - "deferred-leveldown": "~4.0.0", - "level-errors": "~2.0.0", - "level-iterator-stream": "~3.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-packager/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/level-packager/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/level-packager/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/level-packager/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/level-ws": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", - "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", - "dev": true, - "dependencies": { - "readable-stream": "~1.0.15", - "xtend": "~2.1.1" - } - }, - "node_modules/level-ws/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/level-ws/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/levelup": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", - "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", - "dev": true, - "dependencies": { - "deferred-leveldown": "~1.2.1", - "level-codec": "~7.0.0", - "level-errors": "~1.0.3", - "level-iterator-stream": "~1.3.0", - "prr": "~1.0.1", - "semver": "~5.4.1", - "xtend": "~4.0.0" - } - }, - "node_modules/levelup/node_modules/semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/levelup/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", - "dev": true - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, - "node_modules/lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - }, - "node_modules/lodash.toarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", - "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lowdb": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz", - "integrity": "sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.3", - "is-promise": "^2.1.0", - "lodash": "4", - "pify": "^3.0.0", - "steno": "^0.4.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=", - "dev": true - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/ltgt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", - "dev": true - }, - "node_modules/make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/markdown-table": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", - "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", - "dev": true - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memdown": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", - "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", - "dev": true, - "dependencies": { - "abstract-leveldown": "~2.7.1", - "functional-red-black-tree": "^1.0.1", - "immediate": "^3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.1.1" - } - }, - "node_modules/memdown/node_modules/abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "dev": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/memdown/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/memdown/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/merkle-patricia-tree": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz", - "integrity": "sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ==", - "dev": true, - "dependencies": { - "async": "^2.6.1", - "ethereumjs-util": "^5.2.0", - "level-mem": "^3.0.1", - "level-ws": "^1.0.0", - "readable-stream": "^3.0.6", - "rlp": "^2.0.0", - "semaphore": ">=1.0.1" - } - }, - "node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/merkle-patricia-tree/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/merkle-patricia-tree/node_modules/level-ws": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-1.0.0.tgz", - "integrity": "sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.2.8", - "xtend": "^4.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/merkle-patricia-tree/node_modules/level-ws/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/merkle-patricia-tree/node_modules/level-ws/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/merkle-patricia-tree/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/merkle-patricia-tree/node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/merkle-patricia-tree/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/micromatch/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, - "dependencies": { - "mime-db": "1.44.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types/node_modules/mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "dev": true, - "dependencies": { - "dom-walk": "^0.1.0" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dev": true, - "dependencies": { - "minipass": "^2.9.0" - } - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mkdirp-promise": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", - "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", - "dev": true, - "dependencies": { - "mkdirp": "*" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", - "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", - "dev": true, - "dependencies": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "chokidar": "3.3.0", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.5", - "ms": "2.1.1", - "node-environment-flags": "1.0.6", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 8.10.0" - } - }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", - "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.2.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.1.1" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "node_modules/mocha/node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mocha/node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/readdirp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", - "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", - "dev": true, - "dependencies": { - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mock-fs": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.13.0.tgz", - "integrity": "sha512-DD0vOdofJdoaRNtnWcrXe6RQbpHkPPmtqGq14uRX0F8ZKJ5nv89CVTYl/BZdppDxBDaV0hl75htg3abpEWlPZA==", - "dev": true - }, - "node_modules/mri": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", - "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/multimatch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", - "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", - "dev": true, - "dependencies": { - "@types/minimatch": "^3.0.3", - "array-differ": "^3.0.0", - "array-union": "^2.1.0", - "arrify": "^2.0.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", - "dev": true - }, - "node_modules/nano-json-stream-parser": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", - "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=", - "dev": true - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "dev": true - }, - "node_modules/node-emoji": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", - "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==", - "dev": true, - "dependencies": { - "lodash.toarray": "^4.4.0" - } - }, - "node_modules/node-environment-flags": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", - "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", - "dev": true, - "dependencies": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node_modules/node-environment-flags/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "dev": true, - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/node-gyp-build": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", - "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", - "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/nofilter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-1.0.4.tgz", - "integrity": "sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", - "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true, - "dependencies": { - "prepend-http": "^2.0.0", - "query-string": "^5.0.1", - "sort-keys": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/normalize-url/node_modules/sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true, - "dependencies": { - "is-plain-obj": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", - "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", - "dev": true, - "dependencies": { - "config-chain": "^1.1.11", - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz", - "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/number-to-bn": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", - "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", - "dev": true, - "dependencies": { - "bn.js": "4.11.6", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/number-to-bn/node_modules/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign/node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/oboe": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.4.tgz", - "integrity": "sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY=", - "dev": true, - "dependencies": { - "http-https": "^1.0.0" - } - }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/opencollective-postinstall": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", - "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", - "dev": true, - "bin": { - "opencollective-postinstall": "index.js" - } - }, - "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-cancelable": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", - "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-event": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", - "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", - "dev": true, - "dependencies": { - "p-timeout": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-is-promise": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-timeout": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", - "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true, - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/parse-cache-control": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha1-juqz5U+laSD+Fro493+iGqzC104=", - "dev": true - }, - "node_modules/parse-code-context": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-code-context/-/parse-code-context-1.0.0.tgz", - "integrity": "sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-headers": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", - "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==", - "dev": true - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/patch-package": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.2.2.tgz", - "integrity": "sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg==", - "dev": true, - "dependencies": { - "@yarnpkg/lockfile": "^1.1.0", - "chalk": "^2.4.2", - "cross-spawn": "^6.0.5", - "find-yarn-workspace-root": "^1.2.1", - "fs-extra": "^7.0.1", - "is-ci": "^2.0.0", - "klaw-sync": "^6.0.0", - "minimist": "^1.2.0", - "rimraf": "^2.6.3", - "semver": "^5.6.0", - "slash": "^2.0.0", - "tmp": "^0.0.33" - }, - "bin": { - "patch-package": "index.js" - }, - "engines": { - "npm": ">5" - } - }, - "node_modules/patch-package/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/patch-package/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/patch-package/node_modules/slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/patch-package/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-type/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", - "dev": true, - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/please-upgrade-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, - "dependencies": { - "semver-compare": "^1.0.0" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postinstall-postinstall": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz", - "integrity": "sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ==", - "dev": true, - "hasInstallScript": true - }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/prettier": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", - "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/prettier-plugin-solidity": { - "version": "1.0.0-alpha.60", - "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-alpha.60.tgz", - "integrity": "sha512-Dd6T0dVfw0kJrlEnLDFFE3mKRSP7zpT6zcIWvnSW+z4NBl+gmwJ7UJRZHD0CNDD6N48c+zb28xs3oF0ylDaYyg==", - "dev": true, - "dependencies": { - "@solidity-parser/parser": "^0.9.0", - "dir-to-object": "^2.0.0", - "emoji-regex": "^9.0.0", - "escape-string-regexp": "^4.0.0", - "extract-comments": "^1.1.0", - "prettier": "^2.0.5", - "semver": "^7.3.2", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/prettier-plugin-solidity/node_modules/@solidity-parser/parser": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.9.0.tgz", - "integrity": "sha512-u1WzZgzOBFsGAcUhyj8DN/kop1SvrsaRT2ZVvDpVYnFI86YwbLrXCTGxefJzYGnA5Vajbbhi4aRtlxxFh69dfA==", - "dev": true, - "dependencies": { - "antlr4": "^4.8.0" - } - }, - "node_modules/prettier-plugin-solidity/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/prettier-plugin-solidity/node_modules/emoji-regex": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.0.tgz", - "integrity": "sha512-DNc3KFPK18bPdElMJnf/Pkv5TXhxFU3YFDEuGLDRtPmV4rkmCjBkCSEp22u6rBHdSN9Vlp/GK7k98prmE1Jgug==", - "dev": true - }, - "node_modules/prettier-plugin-solidity/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/prettier-plugin-solidity/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/prettier-plugin-solidity/node_modules/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/prettier-plugin-solidity/node_modules/string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/prettier-plugin-solidity/node_modules/string-width/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/prettier-plugin-solidity/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-2.0.2.tgz", - "integrity": "sha512-aLb6vtOTEfJDwi1w+MBTeE20GwPVUYyn6IqNg6TtGpiOB1W3y6vKcsGFjqGeaaEtQgMLSPXTWONqh33UBuwG8A==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "execa": "^2.1.0", - "find-up": "^4.1.0", - "ignore": "^5.1.4", - "mri": "^1.1.4", - "multimatch": "^4.0.0" - }, - "bin": { - "pretty-quick": "bin/pretty-quick.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pretty-quick/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pretty-quick/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/promise": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", - "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", - "dev": true, - "dependencies": { - "asap": "~2.0.6" - } - }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", - "dev": true - }, - "node_modules/proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "dev": true, - "dependencies": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", - "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/query-string": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, - "dependencies": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "node_modules/randomhex": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", - "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=", - "dev": true - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", - "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", - "dev": true, - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.3", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", - "dev": true, - "dependencies": { - "minimatch": "3.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/req-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", - "integrity": "sha1-1AgrTURZgDZkD7c93qAe1T20nrw=", - "dev": true, - "dependencies": { - "req-from": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/req-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/req-from/-/req-from-2.0.0.tgz", - "integrity": "sha1-10GI5H+TeW9Kpx327jWuaJ8+DnA=", - "dev": true, - "dependencies": { - "resolve-from": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request-promise-core": { - "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, - "dependencies": { - "lodash": "^4.17.19" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/request-promise-native": { - "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, - "dependencies": { - "request-promise-core": "1.1.4", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - } - }, - "node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/rlp": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", - "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.1" - }, - "bin": { - "rlp": "bin/rlp" - } - }, - "node_modules/run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true - }, - "node_modules/rustbn.js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", - "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sc-istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.5.tgz", - "integrity": "sha512-7wR5EZFLsC4w0wSm9BUuCgW+OGKAU7PNlW5L0qwVPbh+Q1sfVn2fyzfMXYCm6rkNA5ipaCOt94nApcguQwF5Gg==", - "dev": true, - "dependencies": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "istanbul": "lib/cli.js" - } - }, - "node_modules/sc-istanbul/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/sc-istanbul/node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sc-istanbul/node_modules/glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/sc-istanbul/node_modules/has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sc-istanbul/node_modules/resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "node_modules/sc-istanbul/node_modules/supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "dependencies": { - "has-flag": "^1.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "dev": true - }, - "node_modules/scrypt-shim": { - "resolved": "git+ssh://git@github.com/web3-js/scrypt-shim.git#aafdadda13e660e25e1c525d1f5b2443f5eb1ebb", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "scryptsy": "^2.1.0", - "semver": "^6.3.0" - } - }, - "node_modules/scryptsy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz", - "integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==", - "dev": true - }, - "node_modules/secp256k1": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", - "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "elliptic": "^6.5.2", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/seek-bzip": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", - "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", - "dev": true, - "dependencies": { - "commander": "^2.8.1" - }, - "bin": { - "seek-bunzip": "bin/seek-bunzip", - "seek-table": "bin/seek-bzip-table" - } - }, - "node_modules/semaphore": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", - "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true - }, - "node_modules/semver-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", - "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/servify": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", - "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", - "dev": true, - "dependencies": { - "body-parser": "^1.16.0", - "cors": "^2.8.1", - "express": "^4.14.0", - "request": "^2.79.0", - "xhr": "^2.3.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/sha1": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", - "integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=", - "dev": true, - "dependencies": { - "charenc": ">= 0.0.1", - "crypt": ">= 0.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shelljs": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", - "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", - "dev": true, - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true - }, - "node_modules/simple-get": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", - "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", - "dev": true, - "dependencies": { - "decompress-response": "^3.3.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/snapdragon/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/solc": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.6.8.tgz", - "integrity": "sha512-7URBAisWVjO7dwWNpEkQ5dpRSpSF4Wm0aD5EB82D5BQKh+q7jhOxhgkG4K5gax/geM0kPZUAxnaLcgl2ZXBgMQ==", - "dev": true, - "dependencies": { - "command-exists": "^1.2.8", - "commander": "3.0.2", - "fs-extra": "^0.30.0", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "require-from-string": "^2.0.0", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "bin": { - "solcjs": "solcjs" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/solc/node_modules/commander": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", - "dev": true - }, - "node_modules/solc/node_modules/fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/solc/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/solc/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/solc/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/solc/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/solidity-coverage": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.10.tgz", - "integrity": "sha512-F98rYoD3bscB9qIJJrqkk+o93GbOWTT54VgfO97PrcWAenOFIC1EI5DzGJSrMvmFFfr8fsMPR89on6JR0Xf/Ig==", - "dev": true, - "dependencies": { - "@solidity-parser/parser": "^0.7.0", - "@truffle/provider": "^0.1.17", - "chalk": "^2.4.2", - "death": "^1.1.0", - "detect-port": "^1.3.0", - "fs-extra": "^8.1.0", - "ganache-cli": "6.9.0", - "ghost-testrpc": "^0.0.2", - "global-modules": "^2.0.0", - "globby": "^10.0.1", - "jsonschema": "^1.2.4", - "lodash": "^4.17.15", - "node-emoji": "^1.10.0", - "pify": "^4.0.1", - "recursive-readdir": "^2.2.2", - "sc-istanbul": "^0.4.5", - "shelljs": "^0.8.3", - "web3": "1.2.6" - }, - "bin": { - "solidity-coverage": "plugins/bin.js" - } - }, - "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.7.1.tgz", - "integrity": "sha512-5ma2uuwPAEX1TPl2rAPAAuGlBkKnn2oUKQvnhTFlDIB8U/KDWX77FpHtL6Rcz+OwqSCWx9IClxACgyIEJ/GhIw==", - "dev": true - }, - "node_modules/solidity-coverage/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/solidity-coverage/node_modules/globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/solidity-coverage/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "dependencies": { - "is-plain-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sort-keys-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", - "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", - "dev": true, - "dependencies": { - "sort-keys": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", - "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", - "dev": true - }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sshpk/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "node_modules/stacktrace-parser": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", - "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", - "dev": true, - "dependencies": { - "type-fest": "^0.7.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/stacktrace-parser/node_modules/type-fest": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/steno": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", - "integrity": "sha1-BxEFvfwobmYVwEA8J+nXtdy4Vcs=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.3" - } - }, - "node_modules/strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", - "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "node_modules/string.prototype.trimend/node_modules/es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.trimend/node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", - "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "node_modules/string.prototype.trimstart/node_modules/es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.trimstart/node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", - "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", - "dev": true, - "dependencies": { - "is-natural-number": "^4.0.1" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/swarm-js": { - "version": "0.1.39", - "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.39.tgz", - "integrity": "sha512-QLMqL2rzF6n5s50BptyD6Oi0R1aWlJC5Y17SRIVXRj6OR1DRIPM7nepvrxxkjA1zNzFz6mUOMjfeqeDaWB7OOg==", - "dev": true, - "dependencies": { - "bluebird": "^3.5.0", - "buffer": "^5.0.5", - "decompress": "^4.0.0", - "eth-lib": "^0.1.26", - "fs-extra": "^4.0.2", - "got": "^7.1.0", - "mime-types": "^2.1.16", - "mkdirp-promise": "^5.0.1", - "mock-fs": "^4.1.0", - "setimmediate": "^1.0.5", - "tar": "^4.0.2", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/swarm-js/node_modules/eth-lib": { - "version": "0.1.29", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz", - "integrity": "sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "nano-json-stream-parser": "^0.1.2", - "servify": "^0.1.12", - "ws": "^3.0.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/swarm-js/node_modules/fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "node_modules/swarm-js/node_modules/got": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", - "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", - "dev": true, - "dependencies": { - "decompress-response": "^3.2.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-plain-obj": "^1.1.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "p-cancelable": "^0.3.0", - "p-timeout": "^1.1.1", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "url-parse-lax": "^1.0.0", - "url-to-options": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/swarm-js/node_modules/p-cancelable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/swarm-js/node_modules/p-timeout": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", - "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", - "dev": true, - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/swarm-js/node_modules/prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/swarm-js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/swarm-js/node_modules/url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "dependencies": { - "prepend-http": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/swarm-js/node_modules/ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "dependencies": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - }, - "node_modules/sync-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", - "integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==", - "dev": true, - "dependencies": { - "http-response-object": "^3.0.1", - "sync-rpc": "^1.2.1", - "then-request": "^6.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/sync-rpc": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz", - "integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==", - "dev": true, - "dependencies": { - "get-port": "^3.1.0" - } - }, - "node_modules/tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "dev": true, - "dependencies": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - }, - "engines": { - "node": ">=4.5" - } - }, - "node_modules/tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, - "dependencies": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/tar-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/tar-stream/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/tar-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/tar-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/tar-stream/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/temp-hardhat-etherscan": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/temp-hardhat-etherscan/-/temp-hardhat-etherscan-2.0.2.tgz", - "integrity": "sha512-q9+OMPXlsXZ+2fnF+Xmvv0J9vNJChwOXVGJIATiDJr7Qe8LzTwgs55C4l4NKMWPLe4PE9UjcQMVntRfXGTF9vA==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.0.2", - "@ethersproject/address": "^5.0.2", - "cbor": "^5.0.2", - "fs-extra": "^7.0.1", - "lodash": "^4.17.11", - "node-fetch": "^2.6.0", - "semver": "^6.3.0" - } - }, - "node_modules/test-value": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", - "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", - "dev": true, - "dependencies": { - "array-back": "^1.0.3", - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/test-value/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/testrpc": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/testrpc/-/testrpc-0.0.1.tgz", - "integrity": "sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA==", - "dev": true - }, - "node_modules/then-request": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", - "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", - "dev": true, - "dependencies": { - "@types/concat-stream": "^1.6.0", - "@types/form-data": "0.0.33", - "@types/node": "^8.0.0", - "@types/qs": "^6.2.31", - "caseless": "~0.12.0", - "concat-stream": "^1.6.0", - "form-data": "^2.2.0", - "http-basic": "^8.1.1", - "http-response-object": "^3.0.1", - "promise": "^8.0.0", - "qs": "^6.4.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/then-request/node_modules/@types/node": { - "version": "8.10.66", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", - "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/tmp-promise": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.2.tgz", - "integrity": "sha512-OyCLAKU1HzBjL6Ev3gxUeraJNlbNingmi8IrHHEsYH8LTmEuhvYfqvhn2F/je+mjf4N58UmZ96OMEy1JanSCpA==", - "dependencies": { - "tmp": "^0.2.0" - } - }, - "node_modules/to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", - "dev": true - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tough-cookie/node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/true-case-path": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-2.2.1.tgz", - "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==", - "dev": true - }, - "node_modules/ts-essentials": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-2.0.12.tgz", - "integrity": "sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w==", - "dev": true - }, - "node_modules/ts-generator": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ts-generator/-/ts-generator-0.1.1.tgz", - "integrity": "sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ==", - "dev": true, - "dependencies": { - "@types/mkdirp": "^0.5.2", - "@types/prettier": "^2.1.1", - "@types/resolve": "^0.0.8", - "chalk": "^2.4.1", - "glob": "^7.1.2", - "mkdirp": "^0.5.1", - "prettier": "^2.1.2", - "resolve": "^1.8.1", - "ts-essentials": "^1.0.0" - }, - "bin": { - "ts-generator": "dist/cli/run.js" - } - }, - "node_modules/ts-generator/node_modules/ts-essentials": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-1.0.4.tgz", - "integrity": "sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ==", - "dev": true - }, - "node_modules/ts-node": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", - "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", - "dev": true, - "dependencies": { - "arg": "^4.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "bin": { - "tslint": "bin/tslint" - }, - "engines": { - "node": ">=4.8.0" - } - }, - "node_modules/tslint-config-prettier": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", - "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", - "dev": true, - "bin": { - "tslint-config-prettier-check": "bin/check.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/tslint-plugin-prettier": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslint-plugin-prettier/-/tslint-plugin-prettier-2.3.0.tgz", - "integrity": "sha512-F9e4K03yc9xuvv+A0v1EmjcnDwpz8SpCD8HzqSDe0eyg34cBinwn9JjmnnRrNAs4HdleRQj7qijp+P/JTxt4vA==", - "dev": true, - "dependencies": { - "eslint-plugin-prettier": "^2.2.0", - "lines-and-columns": "^1.1.6", - "tslib": "^1.7.1" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/tslint/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/tslint/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/tsort": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=", - "dev": true - }, - "node_modules/tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true - }, - "node_modules/tweetnacl-util": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", - "dev": true - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typechain": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-4.0.0.tgz", - "integrity": "sha512-XQUojf02bXyxXNGI0WeCphnh++5eWr9wYH8jm0XqHNv8yENpFrRyX8ffVlkhCnDOOB/jEJJVQytLAOU+Qn0N9Q==", - "dev": true, - "dependencies": { - "command-line-args": "^4.0.7", - "debug": "^4.1.1", - "fs-extra": "^7.0.0", - "js-sha3": "^0.8.0", - "lodash": "^4.17.15", - "ts-essentials": "^6.0.3", - "ts-generator": "^0.1.1" - }, - "bin": { - "typechain": "dist/cli/cli.js" - } - }, - "node_modules/typechain/node_modules/ts-essentials": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-6.0.7.tgz", - "integrity": "sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw==", - "dev": true - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typescript": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", - "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/typical": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", - "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", - "dev": true - }, - "node_modules/uglify-js": { - "version": "3.11.6", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.6.tgz", - "integrity": "sha512-oASI1FOJ7BBFkSCNDZ446EgkSuHkOZBuqRFrwXIKWCoXw8ZXQETooTQjkAcBS03Acab7ubCKsXnwuV2svy061g==", - "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true - }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "node_modules/underscore": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", - "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", - "dev": true - }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/url-set-query": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", - "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=", - "dev": true - }, - "node_modules/url-to-options": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", - "dev": true - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/web3": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.6.tgz", - "integrity": "sha512-tpu9fLIComgxGrFsD8LUtA4s4aCZk7px8UfcdEy6kS2uDi/ZfR07KJqpXZMij7Jvlq+cQrTAhsPSiBVvoMaivA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@types/node": "^12.6.1", - "web3-bzz": "1.2.6", - "web3-core": "1.2.6", - "web3-eth": "1.2.6", - "web3-eth-personal": "1.2.6", - "web3-net": "1.2.6", - "web3-shh": "1.2.6", - "web3-utils": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-bzz": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.2.tgz", - "integrity": "sha512-b1O2ObsqUN1lJxmFSjvnEC4TsaCbmh7Owj3IAIWTKqL9qhVgx7Qsu5O9cD13pBiSPNZJ68uJPaKq380QB4NWeA==", - "dev": true, - "dependencies": { - "@types/node": "^10.12.18", - "got": "9.6.0", - "swarm-js": "0.1.39", - "underscore": "1.9.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-bzz/node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/web3-bzz/node_modules/@types/node": { - "version": "10.17.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", - "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", - "dev": true - }, - "node_modules/web3-bzz/node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/web3-bzz/node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/web3-bzz/node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/web3-bzz/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/web3-bzz/node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/web3-bzz/node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "node_modules/web3-bzz/node_modules/normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/web3-bzz/node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/web3-core": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.2.tgz", - "integrity": "sha512-miHAX3qUgxV+KYfaOY93Hlc3kLW2j5fH8FJy6kSxAv+d4d5aH0wwrU2IIoJylQdT+FeenQ38sgsCnFu9iZ1hCQ==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.4", - "@types/node": "^12.6.1", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-core-requestmanager": "1.2.2", - "web3-utils": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-helpers": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.2.tgz", - "integrity": "sha512-HJrRsIGgZa1jGUIhvGz4S5Yh6wtOIo/TMIsSLe+Xay+KVnbseJpPprDI5W3s7H2ODhMQTbogmmUFquZweW2ImQ==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-eth-iban": "1.2.2", - "web3-utils": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-helpers/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/web3-core-helpers/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3-core-helpers/node_modules/web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-method": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.2.tgz", - "integrity": "sha512-szR4fDSBxNHaF1DFqE+j6sFR/afv9Aa36OW93saHZnrh+iXSrYeUUDfugeNcRlugEKeUCkd4CZylfgbK2SKYJA==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.2", - "web3-core-promievent": "1.2.2", - "web3-core-subscriptions": "1.2.2", - "web3-utils": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-method/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/web3-core-method/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3-core-method/node_modules/web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-promievent": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.2.tgz", - "integrity": "sha512-tKvYeT8bkUfKABcQswK6/X79blKTKYGk949urZKcLvLDEaWrM3uuzDwdQT3BNKzQ3vIvTggFPX9BwYh0F1WwqQ==", - "dev": true, - "dependencies": { - "any-promise": "1.3.0", - "eventemitter3": "3.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-requestmanager": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.2.tgz", - "integrity": "sha512-a+gSbiBRHtHvkp78U2bsntMGYGF2eCb6219aMufuZWeAZGXJ63Wc2321PCbA8hF9cQrZI4EoZ4kVLRI4OF15Hw==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.2", - "web3-providers-http": "1.2.2", - "web3-providers-ipc": "1.2.2", - "web3-providers-ws": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-subscriptions": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.2.tgz", - "integrity": "sha512-QbTgigNuT4eicAWWr7ahVpJyM8GbICsR1Ys9mJqzBEwpqS+RXTRVSkwZ2IsxO+iqv6liMNwGregbJLq4urMFcQ==", - "dev": true, - "dependencies": { - "eventemitter3": "3.1.2", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core/node_modules/@types/node": { - "version": "12.19.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", - "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", - "dev": true - }, - "node_modules/web3-core/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/web3-core/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3-core/node_modules/web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.2.tgz", - "integrity": "sha512-UXpC74mBQvZzd4b+baD4Ocp7g+BlwxhBHumy9seyE/LMIcMlePXwCKzxve9yReNpjaU16Mmyya6ZYlyiKKV8UA==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-core-subscriptions": "1.2.2", - "web3-eth-abi": "1.2.2", - "web3-eth-accounts": "1.2.2", - "web3-eth-contract": "1.2.2", - "web3-eth-ens": "1.2.2", - "web3-eth-iban": "1.2.2", - "web3-eth-personal": "1.2.2", - "web3-net": "1.2.2", - "web3-utils": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-abi": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.2.tgz", - "integrity": "sha512-Yn/ZMgoOLxhTVxIYtPJ0eS6pnAnkTAaJgUJh1JhZS4ekzgswMfEYXOwpMaD5eiqPJLpuxmZFnXnBZlnQ1JMXsw==", - "dev": true, - "dependencies": { - "ethers": "4.0.0-beta.3", - "underscore": "1.9.1", - "web3-utils": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-abi/node_modules/@types/node": { - "version": "10.17.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", - "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", - "dev": true - }, - "node_modules/web3-eth-abi/node_modules/elliptic": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", - "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", - "dev": true, - "dependencies": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/web3-eth-abi/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3-eth-abi/node_modules/eth-lib/node_modules/elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", - "dev": true, - "dependencies": { - "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" - } - }, - "node_modules/web3-eth-abi/node_modules/ethers": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", - "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", - "dev": true, - "dependencies": { - "@types/node": "^10.3.2", - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "elliptic": "6.3.3", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.3", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - } - }, - "node_modules/web3-eth-abi/node_modules/hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/web3-eth-abi/node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, - "node_modules/web3-eth-abi/node_modules/scrypt-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", - "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", - "dev": true - }, - "node_modules/web3-eth-abi/node_modules/setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", - "dev": true - }, - "node_modules/web3-eth-abi/node_modules/uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", - "dev": true - }, - "node_modules/web3-eth-abi/node_modules/web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-abi/node_modules/web3-utils/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/web3-eth-accounts": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.2.tgz", - "integrity": "sha512-KzHOEyXOEZ13ZOkWN3skZKqSo5f4Z1ogPFNn9uZbKCz+kSp+gCAEKxyfbOsB/JMAp5h7o7pb6eYsPCUBJmFFiA==", - "dev": true, - "dependencies": { - "any-promise": "1.3.0", - "crypto-browserify": "3.12.0", - "eth-lib": "0.2.7", - "ethereumjs-common": "^1.3.2", - "ethereumjs-tx": "^2.1.1", - "scrypt-shim": "github:web3-js/scrypt-shim", - "underscore": "1.9.1", - "uuid": "3.3.2", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-utils": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-accounts/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3-eth-accounts/node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/web3-eth-accounts/node_modules/web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-accounts/node_modules/web3-utils/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/web3-eth-contract": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.2.tgz", - "integrity": "sha512-EKT2yVFws3FEdotDQoNsXTYL798+ogJqR2//CaGwx3p0/RvQIgfzEwp8nbgA6dMxCsn9KOQi7OtklzpnJMkjtA==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.4", - "underscore": "1.9.1", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-core-promievent": "1.2.2", - "web3-core-subscriptions": "1.2.2", - "web3-eth-abi": "1.2.2", - "web3-utils": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-contract/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/web3-eth-contract/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3-eth-contract/node_modules/web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-ens": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.2.tgz", - "integrity": "sha512-CFjkr2HnuyMoMFBoNUWojyguD4Ef+NkyovcnUc/iAb9GP4LHohKrODG4pl76R5u61TkJGobC2ij6TyibtsyVYg==", - "dev": true, - "dependencies": { - "eth-ens-namehash": "2.0.8", - "underscore": "1.9.1", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-promievent": "1.2.2", - "web3-eth-abi": "1.2.2", - "web3-eth-contract": "1.2.2", - "web3-utils": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-ens/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/web3-eth-ens/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3-eth-ens/node_modules/web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-iban": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.2.tgz", - "integrity": "sha512-gxKXBoUhaTFHr0vJB/5sd4i8ejF/7gIsbM/VvemHT3tF5smnmY6hcwSMmn7sl5Gs+83XVb/BngnnGkf+I/rsrQ==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "web3-utils": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-iban/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/web3-eth-iban/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3-eth-iban/node_modules/web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-personal": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.2.tgz", - "integrity": "sha512-4w+GLvTlFqW3+q4xDUXvCEMU7kRZ+xm/iJC8gm1Li1nXxwwFbs+Y+KBK6ZYtoN1qqAnHR+plYpIoVo27ixI5Rg==", - "dev": true, - "dependencies": { - "@types/node": "^12.6.1", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-net": "1.2.2", - "web3-utils": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-personal/node_modules/@types/node": { - "version": "12.19.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", - "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", - "dev": true - }, - "node_modules/web3-eth-personal/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/web3-eth-personal/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3-eth-personal/node_modules/web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/web3-eth/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3-eth/node_modules/web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-net": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.2.tgz", - "integrity": "sha512-K07j2DXq0x4UOJgae65rWZKraOznhk8v5EGSTdFqASTx7vWE/m+NqBijBYGEsQY1lSMlVaAY9UEQlcXK5HzXTw==", - "dev": true, - "dependencies": { - "web3-core": "1.2.2", - "web3-core-method": "1.2.2", - "web3-utils": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-net/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/web3-net/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3-net/node_modules/web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-providers-http": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.2.tgz", - "integrity": "sha512-BNZ7Hguy3eBszsarH5gqr9SIZNvqk9eKwqwmGH1LQS1FL3NdoOn7tgPPdddrXec4fL94CwgNk4rCU+OjjZRNDg==", - "dev": true, - "dependencies": { - "web3-core-helpers": "1.2.2", - "xhr2-cookies": "1.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-providers-ipc": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.2.tgz", - "integrity": "sha512-t97w3zi5Kn/LEWGA6D9qxoO0LBOG+lK2FjlEdCwDQatffB/+vYrzZ/CLYVQSoyFZAlsDoBasVoYSWZK1n39aHA==", - "dev": true, - "dependencies": { - "oboe": "2.1.4", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-providers-ws": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.2.tgz", - "integrity": "sha512-Wb1mrWTGMTXOpJkL0yGvL/WYLt8fUIXx8k/l52QB2IiKzvyd42dTWn4+j8IKXGSYYzOm7NMqv6nhA5VDk12VfA==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.2", - "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-shh": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.2.tgz", - "integrity": "sha512-og258NPhlBn8yYrDWjoWBBb6zo1OlBgoWGT+LL5/LPqRbjPe09hlOYHgscAAr9zZGtohTOty7RrxYw6Z6oDWCg==", - "dev": true, - "dependencies": { - "web3-core": "1.2.2", - "web3-core-method": "1.2.2", - "web3-core-subscriptions": "1.2.2", - "web3-net": "1.2.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.0.tgz", - "integrity": "sha512-2mS5axFCbkhicmoDRuJeuo0TVGQDgC2sPi/5dblfVC+PMtX0efrb8Xlttv/eGkq7X4E83Pds34FH98TP2WOUZA==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "eth-lib": "0.2.8", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/web3/node_modules/@types/node": { - "version": "12.19.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", - "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", - "dev": true - }, - "node_modules/web3/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/web3/node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/web3/node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/web3/node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/web3/node_modules/eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3/node_modules/ethers": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", - "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", - "dev": true, - "dependencies": { - "@types/node": "^10.3.2", - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "elliptic": "6.3.3", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.3", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - } - }, - "node_modules/web3/node_modules/ethers/node_modules/@types/node": { - "version": "10.17.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", - "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", - "dev": true - }, - "node_modules/web3/node_modules/ethers/node_modules/elliptic": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", - "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", - "dev": true, - "dependencies": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/web3/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/web3/node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/web3/node_modules/hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/web3/node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "node_modules/web3/node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, - "node_modules/web3/node_modules/normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/web3/node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/web3/node_modules/scrypt-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", - "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", - "dev": true - }, - "node_modules/web3/node_modules/setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", - "dev": true - }, - "node_modules/web3/node_modules/uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", - "dev": true - }, - "node_modules/web3/node_modules/web3-bzz": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.6.tgz", - "integrity": "sha512-9NiHLlxdI1XeFtbPJAmi2jnnIHVF+GNy517wvOS72P7ZfuJTPwZaSNXfT01vWgPPE9R96/uAHDWHOg+T4WaDQQ==", - "dev": true, - "dependencies": { - "@types/node": "^10.12.18", - "got": "9.6.0", - "swarm-js": "0.1.39", - "underscore": "1.9.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-bzz/node_modules/@types/node": { - "version": "10.17.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", - "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", - "dev": true - }, - "node_modules/web3/node_modules/web3-core": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.6.tgz", - "integrity": "sha512-y/QNBFtr5cIR8vxebnotbjWJpOnO8LDYEAzZjeRRUJh2ijmhjoYk7dSNx9ExgC0UCfNFRoNCa9dGRu/GAxwRlw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.4", - "@types/node": "^12.6.1", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-core-requestmanager": "1.2.6", - "web3-utils": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-core-helpers": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.6.tgz", - "integrity": "sha512-gYKWmC2HmO7RcDzpo4L1K8EIoy5L8iubNDuTC6q69UxczwqKF/Io0kbK/1Z10Av++NlzOSiuyGp2gc4t4UOsDw==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-eth-iban": "1.2.6", - "web3-utils": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-core-method": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.6.tgz", - "integrity": "sha512-r2dzyPEonqkBg7Mugq5dknhV5PGaZTHBZlS/C+aMxNyQs3T3eaAsCTqlQDitwNUh/sUcYPEGF0Vo7ahYK4k91g==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6", - "web3-core-promievent": "1.2.6", - "web3-core-subscriptions": "1.2.6", - "web3-utils": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-core-promievent": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.6.tgz", - "integrity": "sha512-km72kJef/qtQNiSjDJJVHIZvoVOm6ytW3FCYnOcCs7RIkviAb5JYlPiye0o4pJOLzCXYID7DK7Q9bhY8qWb1lw==", - "dev": true, - "dependencies": { - "any-promise": "1.3.0", - "eventemitter3": "3.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-core-requestmanager": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.6.tgz", - "integrity": "sha512-QU2cbsj9Dm0r6om40oSwk8Oqbp3wTa08tXuMpSmeOTkGZ3EMHJ1/4LiJ8shwg1AvPMrKVU0Nri6+uBNCdReZ+g==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6", - "web3-providers-http": "1.2.6", - "web3-providers-ipc": "1.2.6", - "web3-providers-ws": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-core-subscriptions": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.6.tgz", - "integrity": "sha512-M0PzRrP2Ct13x3wPulFtc5kENH4UtnPxO9YxkfQlX2WRKENWjt4Rfq+BCVGYEk3rTutDfWrjfzjmqMRvXqEY5Q==", - "dev": true, - "dependencies": { - "eventemitter3": "3.1.2", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-eth": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.6.tgz", - "integrity": "sha512-ROWlDPzh4QX6tlGGGlAK6X4kA2n0/cNj/4kb0nNVWkRouGmYO0R8k6s47YxYHvGiXt0s0++FUUv5vAbWovtUQw==", - "dev": true, - "dependencies": { - "underscore": "1.9.1", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-core-subscriptions": "1.2.6", - "web3-eth-abi": "1.2.6", - "web3-eth-accounts": "1.2.6", - "web3-eth-contract": "1.2.6", - "web3-eth-ens": "1.2.6", - "web3-eth-iban": "1.2.6", - "web3-eth-personal": "1.2.6", - "web3-net": "1.2.6", - "web3-utils": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-eth-abi": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.6.tgz", - "integrity": "sha512-w9GAyyikn8nSifSDZxAvU9fxtQSX+W2xQWMmrtTXmBGCaE4/ywKOSPAO78gq8AoU4Wq5yqVGKZLLbfpt7/sHlA==", - "dev": true, - "dependencies": { - "ethers": "4.0.0-beta.3", - "underscore": "1.9.1", - "web3-utils": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-eth-accounts": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.6.tgz", - "integrity": "sha512-cDVtonHRgzqi/ZHOOf8kfCQWFEipcfQNAMzXIaKZwc0UUD9mgSI5oJrN45a89Ze+E6Lz9m77cDG5Ax9zscSkcw==", - "dev": true, - "dependencies": { - "@web3-js/scrypt-shim": "^0.1.0", - "any-promise": "1.3.0", - "crypto-browserify": "3.12.0", - "eth-lib": "^0.2.8", - "ethereumjs-common": "^1.3.2", - "ethereumjs-tx": "^2.1.1", - "underscore": "1.9.1", - "uuid": "3.3.2", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-utils": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-eth-accounts/node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3/node_modules/web3-eth-accounts/node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/web3/node_modules/web3-eth-contract": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.6.tgz", - "integrity": "sha512-ak4xbHIhWgsbdPCkSN+HnQc1SH4c856y7Ly+S57J/DQVzhFZemK5HvWdpwadJrQTcHET3ZeId1vq3kmW7UYodw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.4", - "underscore": "1.9.1", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-core-promievent": "1.2.6", - "web3-core-subscriptions": "1.2.6", - "web3-eth-abi": "1.2.6", - "web3-utils": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-eth-ens": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.6.tgz", - "integrity": "sha512-8UEqt6fqR/dji/jBGPFAyBs16OJjwi0t2dPWXPyGXmty/fH+osnXwWXE4HRUyj4xuafiM5P1YkXMsPhKEadjiw==", - "dev": true, - "dependencies": { - "eth-ens-namehash": "2.0.8", - "underscore": "1.9.1", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-promievent": "1.2.6", - "web3-eth-abi": "1.2.6", - "web3-eth-contract": "1.2.6", - "web3-utils": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-eth-iban": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.6.tgz", - "integrity": "sha512-TPMc3BW9Iso7H+9w+ytbqHK9wgOmtocyCD3PaAe5Eie50KQ/j7ThA60dGJnxItVo6yyRv5pZAYxPVob9x/fJlg==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "web3-utils": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-eth-personal": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.6.tgz", - "integrity": "sha512-T2NUkh1plY8d7wePXSoHnaiKOd8dLNFaQfgBl9JHU6S7IJrG9jnYD9bVxLEgRUfHs9gKf9tQpDf7AcPFdq/A8g==", - "dev": true, - "dependencies": { - "@types/node": "^12.6.1", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-net": "1.2.6", - "web3-utils": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-net": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.6.tgz", - "integrity": "sha512-hsNHAPddrhgjWLmbESW0KxJi2GnthPcow0Sqpnf4oB6+/+ZnQHU9OsIyHb83bnC1OmunrK2vf9Ye2mLPdFIu3A==", - "dev": true, - "dependencies": { - "web3-core": "1.2.6", - "web3-core-method": "1.2.6", - "web3-utils": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-providers-http": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.6.tgz", - "integrity": "sha512-2+SaFCspb5f82QKuHB3nEPQOF9iSWxRf7c18fHtmnLNVkfG9SwLN1zh67bYn3tZGUdOI3gj8aX4Uhfpwx9Ezpw==", - "dev": true, - "dependencies": { - "web3-core-helpers": "1.2.6", - "xhr2-cookies": "1.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-providers-ipc": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.6.tgz", - "integrity": "sha512-b0Es+/GTZyk5FG3SgUDW+2/mBwJAXWt5LuppODptiOas8bB2khLjG6+Gm1K4uwOb+1NJGPt5mZZ8Wi7vibtQ+A==", - "dev": true, - "dependencies": { - "oboe": "2.1.4", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-providers-ws": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.6.tgz", - "integrity": "sha512-20waSYX+gb5M5yKhug5FIwxBBvkKzlJH7sK6XEgdOx6BZ9YYamLmvg9wcRVtnSZO8hV/3cWenO/tRtTrHVvIgQ==", - "dev": true, - "dependencies": { - "@web3-js/websocket": "^1.0.29", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-shh": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.6.tgz", - "integrity": "sha512-rouWyOOM6YMbLQd65grpj8BBezQfgNeRRX+cGyW4xsn6Xgu+B73Zvr6OtA/ftJwwa9bqHGpnLrrLMeWyy4YLUw==", - "dev": true, - "dependencies": { - "web3-core": "1.2.6", - "web3-core-method": "1.2.6", - "web3-core-subscriptions": "1.2.6", - "web3-net": "1.2.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3/node_modules/web3-utils": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.6.tgz", - "integrity": "sha512-8/HnqG/l7dGmKMgEL9JeKPTtjScxOePTzopv5aaKFExPfaBrYRkgoMqhoowCiAl/s16QaTn4DoIF1QC4YsT7Mg==", - "dev": true, - "dependencies": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/websocket": { - "resolved": "git+ssh://git@github.com/web3-js/WebSocket-Node.git#ef5ea2f41daf4a2113b80c9223df884b4d56c400", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "nan": "^2.14.0", - "typedarray-to-buffer": "^3.1.5", - "yaeti": "^0.0.6" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/websocket/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/websocket/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/which-pm-runs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", - "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", - "dev": true - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true, - "bin": { - "window-size": "cli.js" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/ws": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", - "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==", - "dev": true, - "engines": { - "node": ">=8.3.0" - } - }, - "node_modules/xhr": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", - "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", - "dev": true, - "dependencies": { - "global": "~4.3.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/xhr-request": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", - "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", - "dev": true, - "dependencies": { - "buffer-to-arraybuffer": "^0.0.5", - "object-assign": "^4.1.1", - "query-string": "^5.0.1", - "simple-get": "^2.7.0", - "timed-out": "^4.0.1", - "url-set-query": "^1.0.0", - "xhr": "^2.0.4" - } - }, - "node_modules/xhr-request-promise": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz", - "integrity": "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==", - "dev": true, - "dependencies": { - "xhr-request": "^1.1.0" - } - }, - "node_modules/xhr/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/xhr2-cookies": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", - "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", - "dev": true, - "dependencies": { - "cookiejar": "^2.1.1" - } - }, - "node_modules/xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "node_modules/yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", - "dev": true, - "engines": { - "node": ">=0.10.32" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yaml": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", - "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "dev": true, - "dependencies": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - } - }, "dependencies": { "@babel/code-frame": { "version": "7.10.4", @@ -27128,7 +1798,7 @@ "requires": { "underscore": "1.9.1", "web3-core-helpers": "1.2.1", - "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" + "websocket": "websocket@github:web3-js/WebSocket-Node#polyfill/globalThis" } }, "web3-shh": { @@ -30913,11 +5583,13 @@ "dependencies": { "ansi-regex": { "version": "4.1.0", + "resolved": false, "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "ansi-styles": { "version": "3.2.1", + "resolved": false, "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { @@ -30926,6 +5598,7 @@ }, "bindings": { "version": "1.5.0", + "resolved": false, "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, "requires": { @@ -30934,6 +5607,7 @@ }, "bip66": { "version": "1.1.5", + "resolved": false, "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", "dev": true, "requires": { @@ -30942,16 +5616,19 @@ }, "bn.js": { "version": "4.11.8", + "resolved": false, "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, "brorand": { "version": "1.1.0", + "resolved": false, "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, "browserify-aes": { "version": "1.2.0", + "resolved": false, "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -30965,21 +5642,25 @@ }, "buffer-from": { "version": "1.1.1", + "resolved": false, "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, "buffer-xor": { "version": "1.0.3", + "resolved": false, "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, "camelcase": { "version": "5.3.1", + "resolved": false, "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "cipher-base": { "version": "1.0.4", + "resolved": false, "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { @@ -30989,6 +5670,7 @@ }, "cliui": { "version": "5.0.0", + "resolved": false, "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { @@ -30999,6 +5681,7 @@ }, "color-convert": { "version": "1.9.3", + "resolved": false, "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { @@ -31007,11 +5690,13 @@ }, "color-name": { "version": "1.1.3", + "resolved": false, "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "create-hash": { "version": "1.2.0", + "resolved": false, "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { @@ -31024,6 +5709,7 @@ }, "create-hmac": { "version": "1.1.7", + "resolved": false, "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { @@ -31037,6 +5723,7 @@ }, "cross-spawn": { "version": "6.0.5", + "resolved": false, "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { @@ -31049,11 +5736,13 @@ }, "decamelize": { "version": "1.2.0", + "resolved": false, "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "drbg.js": { "version": "1.0.1", + "resolved": false, "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", "dev": true, "requires": { @@ -31064,6 +5753,7 @@ }, "elliptic": { "version": "6.5.0", + "resolved": false, "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", "dev": true, "requires": { @@ -31078,11 +5768,13 @@ }, "emoji-regex": { "version": "7.0.3", + "resolved": false, "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "end-of-stream": { "version": "1.4.1", + "resolved": false, "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { @@ -31091,6 +5783,7 @@ }, "ethereumjs-util": { "version": "6.1.0", + "resolved": false, "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", "dev": true, "requires": { @@ -31105,6 +5798,7 @@ }, "ethjs-util": { "version": "0.1.6", + "resolved": false, "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", "dev": true, "requires": { @@ -31114,6 +5808,7 @@ }, "evp_bytestokey": { "version": "1.0.3", + "resolved": false, "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, "requires": { @@ -31123,6 +5818,7 @@ }, "execa": { "version": "1.0.0", + "resolved": false, "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { @@ -31137,11 +5833,13 @@ }, "file-uri-to-path": { "version": "1.0.0", + "resolved": false, "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "dev": true }, "find-up": { "version": "3.0.0", + "resolved": false, "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { @@ -31150,11 +5848,13 @@ }, "get-caller-file": { "version": "2.0.5", + "resolved": false, "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-stream": { "version": "4.1.0", + "resolved": false, "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "requires": { @@ -31163,6 +5863,7 @@ }, "hash-base": { "version": "3.0.4", + "resolved": false, "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, "requires": { @@ -31172,6 +5873,7 @@ }, "hash.js": { "version": "1.1.7", + "resolved": false, "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, "requires": { @@ -31181,6 +5883,7 @@ }, "hmac-drbg": { "version": "1.0.1", + "resolved": false, "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { @@ -31191,36 +5894,43 @@ }, "inherits": { "version": "2.0.4", + "resolved": false, "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "invert-kv": { "version": "2.0.0", + "resolved": false, "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", + "resolved": false, "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "is-hex-prefixed": { "version": "1.0.0", + "resolved": false, "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", "dev": true }, "is-stream": { "version": "1.1.0", + "resolved": false, "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, "isexe": { "version": "2.0.0", + "resolved": false, "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "keccak": { "version": "1.4.0", + "resolved": false, "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", "dev": true, "requires": { @@ -31232,6 +5942,7 @@ }, "lcid": { "version": "2.0.0", + "resolved": false, "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { @@ -31240,6 +5951,7 @@ }, "locate-path": { "version": "3.0.0", + "resolved": false, "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { @@ -31249,6 +5961,7 @@ }, "map-age-cleaner": { "version": "0.1.3", + "resolved": false, "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", "dev": true, "requires": { @@ -31257,6 +5970,7 @@ }, "md5.js": { "version": "1.3.5", + "resolved": false, "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, "requires": { @@ -31267,6 +5981,7 @@ }, "mem": { "version": "4.3.0", + "resolved": false, "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, "requires": { @@ -31277,31 +5992,37 @@ }, "mimic-fn": { "version": "2.1.0", + "resolved": false, "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "minimalistic-assert": { "version": "1.0.1", + "resolved": false, "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, "minimalistic-crypto-utils": { "version": "1.0.1", + "resolved": false, "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", "dev": true }, "nan": { "version": "2.14.0", + "resolved": false, "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "dev": true }, "nice-try": { "version": "1.0.5", + "resolved": false, "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "npm-run-path": { "version": "2.0.2", + "resolved": false, "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { @@ -31310,6 +6031,7 @@ }, "once": { "version": "1.4.0", + "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { @@ -31318,6 +6040,7 @@ }, "os-locale": { "version": "3.1.0", + "resolved": false, "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { @@ -31328,21 +6051,25 @@ }, "p-defer": { "version": "1.0.0", + "resolved": false, "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", "dev": true }, "p-finally": { "version": "1.0.0", + "resolved": false, "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, "p-is-promise": { "version": "2.1.0", + "resolved": false, "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", "dev": true }, "p-limit": { "version": "2.2.0", + "resolved": false, "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { @@ -31351,6 +6078,7 @@ }, "p-locate": { "version": "3.0.0", + "resolved": false, "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { @@ -31359,21 +6087,25 @@ }, "p-try": { "version": "2.2.0", + "resolved": false, "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "path-exists": { "version": "3.0.0", + "resolved": false, "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, "path-key": { "version": "2.0.1", + "resolved": false, "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "pump": { "version": "3.0.0", + "resolved": false, "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { @@ -31383,16 +6115,19 @@ }, "require-directory": { "version": "2.1.1", + "resolved": false, "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { "version": "2.0.0", + "resolved": false, "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "ripemd160": { "version": "2.0.2", + "resolved": false, "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { @@ -31402,6 +6137,7 @@ }, "rlp": { "version": "2.2.3", + "resolved": false, "integrity": "sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==", "dev": true, "requires": { @@ -31411,11 +6147,13 @@ }, "safe-buffer": { "version": "5.2.0", + "resolved": false, "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", "dev": true }, "secp256k1": { "version": "3.7.1", + "resolved": false, "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", "dev": true, "requires": { @@ -31431,16 +6169,19 @@ }, "semver": { "version": "5.7.0", + "resolved": false, "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true }, "set-blocking": { "version": "2.0.0", + "resolved": false, "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "sha.js": { "version": "2.4.11", + "resolved": false, "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -31450,6 +6191,7 @@ }, "shebang-command": { "version": "1.2.0", + "resolved": false, "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { @@ -31458,21 +6200,25 @@ }, "shebang-regex": { "version": "1.0.0", + "resolved": false, "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, "signal-exit": { "version": "3.0.2", + "resolved": false, "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, "source-map": { "version": "0.6.1", + "resolved": false, "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "source-map-support": { "version": "0.5.12", + "resolved": false, "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", "dev": true, "requires": { @@ -31482,6 +6228,7 @@ }, "string-width": { "version": "3.1.0", + "resolved": false, "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { @@ -31492,6 +6239,7 @@ }, "strip-ansi": { "version": "5.2.0", + "resolved": false, "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { @@ -31500,11 +6248,13 @@ }, "strip-eof": { "version": "1.0.0", + "resolved": false, "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "strip-hex-prefix": { "version": "1.0.0", + "resolved": false, "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", "dev": true, "requires": { @@ -31513,6 +6263,7 @@ }, "which": { "version": "1.3.1", + "resolved": false, "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { @@ -31521,11 +6272,13 @@ }, "which-module": { "version": "2.0.0", + "resolved": false, "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "wrap-ansi": { "version": "5.1.0", + "resolved": false, "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { @@ -31536,16 +6289,19 @@ }, "wrappy": { "version": "1.0.2", + "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "y18n": { "version": "4.0.0", + "resolved": false, "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yargs": { "version": "13.2.4", + "resolved": false, "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", "dev": true, "requires": { @@ -31564,6 +6320,7 @@ }, "yargs-parser": { "version": "13.1.1", + "resolved": false, "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { @@ -38843,23 +13600,6 @@ "dev": true, "optional": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, "string.prototype.trim": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.2.tgz", @@ -38912,6 +13652,23 @@ "es-abstract": "^1.17.5" } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, "strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -39846,14 +14603,14 @@ "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", "dev": true, "requires": { - "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git", + "ethereumjs-abi": "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git", "ethereumjs-util": "^5.1.1" } }, "ethereumjs-abi": { "version": "git+https://git@github.com/ethereumjs/ethereumjs-abi.git#1ce6a1d64235fabe2aaf827fd606def55693508f", - "dev": true, "from": "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git", + "dev": true, "requires": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" @@ -42004,12 +16761,6 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, - "lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=", - "dev": true - }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -42019,6 +16770,12 @@ "yallist": "^3.0.2" } }, + "lru_map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", + "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=", + "dev": true + }, "ltgt": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", @@ -44143,8 +18900,8 @@ }, "scrypt-shim": { "version": "git+ssh://git@github.com/web3-js/scrypt-shim.git#aafdadda13e660e25e1c525d1f5b2443f5eb1ebb", - "dev": true, "from": "scrypt-shim@github:web3-js/scrypt-shim", + "dev": true, "requires": { "scryptsy": "^2.1.0", "semver": "^6.3.0" @@ -44848,15 +19605,6 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "dev": true }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -44943,6 +19691,15 @@ } } }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -46846,7 +21603,7 @@ "eth-lib": "0.2.7", "ethereumjs-common": "^1.3.2", "ethereumjs-tx": "^2.1.1", - "scrypt-shim": "github:web3-js/scrypt-shim", + "scrypt-shim": "scrypt-shim@github:web3-js/scrypt-shim", "underscore": "1.9.1", "uuid": "3.3.2", "web3-core": "1.2.2", @@ -47176,7 +21933,7 @@ "requires": { "underscore": "1.9.1", "web3-core-helpers": "1.2.2", - "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" + "websocket": "websocket@github:web3-js/WebSocket-Node#polyfill/globalThis" } }, "web3-shh": { @@ -47209,8 +21966,8 @@ }, "websocket": { "version": "git+ssh://git@github.com/web3-js/WebSocket-Node.git#ef5ea2f41daf4a2113b80c9223df884b4d56c400", - "dev": true, "from": "websocket@github:web3-js/WebSocket-Node#polyfill/globalThis", + "dev": true, "requires": { "debug": "^2.2.0", "es5-ext": "^0.10.50", diff --git a/package.json b/package.json index 8c78210e..f4f1ace5 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,8 @@ "compile": "SKIP_LOAD=true hardhat compile", "console:fork": "MAINNET_FORK=true hardhat console", "test": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-aave/*.spec.ts", - "test-lp": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-lp/*.spec.ts", - "test-lp-scenarios": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-lp/__setup.spec.ts test-suites/test-lp/scenario.spec.ts", + "test-amm": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-amm/*.spec.ts", + "test-amm-scenarios": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-amm/__setup.spec.ts test-suites/test-amm/scenario.spec.ts", "test-scenarios": "npx hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/scenario.spec.ts", "test-repay-with-collateral": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/repay-with-collateral.spec.ts", "test-liquidate-with-collateral": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/flash-liquidation-with-collateral.spec.ts", @@ -33,19 +33,19 @@ "test-stable-and-atokens": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-transfer.spec.ts test-suites/test-aave/stable-token.spec.ts", "test-subgraph:scenarios": "hardhat --network hardhatevm_docker test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/subgraph-scenarios.spec.ts", "test-weth:main": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/weth-gateway.spec.ts", - "test-weth:lp": "hardhat test test-suites/test-lp/__setup.spec.ts test-suites/test-lp/weth-gateway.spec.ts", + "test-weth:amm": "hardhat test test-suites/test-amm/__setup.spec.ts test-suites/test-amm/weth-gateway.spec.ts", "test-uniswap": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/uniswapAdapters*.spec.ts", "test:main:check-list": "MAINNET_FORK=true TS_NODE_TRANSPILE_ONLY=1 hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/mainnet/check-list.spec.ts", "dev:coverage": "buidler compile --force && buidler coverage --network coverage", "aave:evm:dev:migration": "npm run compile && hardhat aave:dev", "aave:docker:full:migration": "npm run compile && npm run hardhat:docker -- aave:mainnet", "aave:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- aave:mainnet --verify", - "lp:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- lp:mainnet --verify", + "amm:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- amm:mainnet --verify", "aave:kovan:full:initialize": "npm run hardhat:kovan -- full:initialize-lending-pool --verify --pool Aave", "aave:ropsten:full:migration": "npm run compile && npm run hardhat:ropsten -- aave:mainnet --verify", "aave:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- aave:mainnet", "aave:fork:main": "npm run compile && MAINNET_FORK=true hardhat aave:mainnet", - "lp:fork:main": "npm run compile && MAINNET_FORK=true hardhat lp:mainnet", + "amm:fork:main": "npm run compile && MAINNET_FORK=true hardhat amm:mainnet", "aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify", "aave:main:full:initialize": "npm run compile && MAINNET_FORK=true full:initialize-tokens --pool Aave", "prettier:check": "npx prettier -c 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test-suites/test-aave/**/*.ts'", diff --git a/tasks/migrations/lp.mainnet.ts b/tasks/migrations/amm.mainnet.ts similarity index 94% rename from tasks/migrations/lp.mainnet.ts rename to tasks/migrations/amm.mainnet.ts index 4faea738..73efeebe 100644 --- a/tasks/migrations/lp.mainnet.ts +++ b/tasks/migrations/amm.mainnet.ts @@ -4,10 +4,10 @@ import { ConfigNames } from '../../helpers/configuration'; import { printContracts } from '../../helpers/misc-utils'; import { usingTenderly } from '../../helpers/tenderly-utils'; -task('lp:mainnet', 'Deploy development enviroment') +task('amm:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') .setAction(async ({ verify }, DRE) => { - const POOL_NAME = ConfigNames.Lp; + const POOL_NAME = ConfigNames.Amm; await DRE.run('set-DRE'); // Prevent loss of gas verifying all the needed ENVs for Etherscan verification diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-amm/__setup.spec.ts similarity index 93% rename from test-suites/test-lp/__setup.spec.ts rename to test-suites/test-amm/__setup.spec.ts index 23843a6c..4598632c 100644 --- a/test-suites/test-lp/__setup.spec.ts +++ b/test-suites/test-amm/__setup.spec.ts @@ -46,7 +46,7 @@ import { } from '../../helpers/oracles-helpers'; import { DRE, waitForTx } from '../../helpers/misc-utils'; import { initReservesByHelper, configureReservesByHelper } from '../../helpers/init-helpers'; -import LpConfig from '../../markets/lp'; +import AmmConfig from '../../markets/amm'; import { ZERO_ADDRESS } from '../../helpers/constants'; import { getLendingPool, @@ -55,16 +55,16 @@ import { } from '../../helpers/contracts-getters'; import { WETH9Mocked } from '../../types/WETH9Mocked'; -const MOCK_USD_PRICE_IN_WEI = LpConfig.ProtocolGlobalParams.MockUsdPriceInWei; -const ALL_ASSETS_INITIAL_PRICES = LpConfig.Mocks.AllAssetsInitialPrices; -const USD_ADDRESS = LpConfig.ProtocolGlobalParams.UsdAddress; -const MOCK_CHAINLINK_AGGREGATORS_PRICES = LpConfig.Mocks.AllAssetsInitialPrices; -const LENDING_RATE_ORACLE_RATES_COMMON = LpConfig.LendingRateOracleRatesCommon; +const MOCK_USD_PRICE_IN_WEI = AmmConfig.ProtocolGlobalParams.MockUsdPriceInWei; +const ALL_ASSETS_INITIAL_PRICES = AmmConfig.Mocks.AllAssetsInitialPrices; +const USD_ADDRESS = AmmConfig.ProtocolGlobalParams.UsdAddress; +const MOCK_CHAINLINK_AGGREGATORS_PRICES = AmmConfig.Mocks.AllAssetsInitialPrices; +const LENDING_RATE_ORACLE_RATES_COMMON = AmmConfig.LendingRateOracleRatesCommon; const deployAllMockTokens = async (deployer: Signer) => { const tokens: { [symbol: string]: MockContract | MintableERC20 | WETH9Mocked } = {}; - const lpConfigData = getReservesConfigByPool(AavePools.lp); + const ammConfigData = getReservesConfigByPool(AavePools.amm); for (const tokenSymbol of Object.keys(TokenContractId)) { if (tokenSymbol === 'WETH') { @@ -74,7 +74,7 @@ const deployAllMockTokens = async (deployer: Signer) => { } let decimals = 18; - let configData = (lpConfigData)[tokenSymbol]; + let configData = (ammConfigData)[tokenSymbol]; if (!configData) { decimals = 18; @@ -97,7 +97,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const mockTokens = await deployAllMockTokens(deployer); - const addressesProvider = await deployLendingPoolAddressesProvider(LpConfig.MarketId); + const addressesProvider = await deployLendingPoolAddressesProvider(AmmConfig.MarketId); await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin)); //setting users[1] as emergency admin, which is in position 2 in the DRE addresses list @@ -227,7 +227,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { aaveAdmin ); - const reservesParams = getReservesConfigByPool(AavePools.lp); + const reservesParams = getReservesConfigByPool(AavePools.amm); const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address); @@ -236,7 +236,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { console.log('Initialize configuration'); - const config = loadPoolConfig(ConfigNames.Lp); + const config = loadPoolConfig(ConfigNames.Amm); const { ATokenNamePrefix, @@ -292,7 +292,7 @@ before(async () => { const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; if (MAINNET_FORK) { - await rawBRE.run('lp:mainnet'); + await rawBRE.run('amm:mainnet'); } else { console.log('-> Deploying test environment...'); await buildTestEnv(deployer, secondaryWallet); diff --git a/test-suites/test-lp/addresses-provider-registry.spec.ts b/test-suites/test-amm/addresses-provider-registry.spec.ts similarity index 100% rename from test-suites/test-lp/addresses-provider-registry.spec.ts rename to test-suites/test-amm/addresses-provider-registry.spec.ts diff --git a/test-suites/test-lp/atoken-modifiers.spec.ts b/test-suites/test-amm/atoken-modifiers.spec.ts similarity index 100% rename from test-suites/test-lp/atoken-modifiers.spec.ts rename to test-suites/test-amm/atoken-modifiers.spec.ts diff --git a/test-suites/test-lp/atoken-permit.spec.ts b/test-suites/test-amm/atoken-permit.spec.ts similarity index 100% rename from test-suites/test-lp/atoken-permit.spec.ts rename to test-suites/test-amm/atoken-permit.spec.ts diff --git a/test-suites/test-lp/atoken-transfer.spec.ts b/test-suites/test-amm/atoken-transfer.spec.ts similarity index 98% rename from test-suites/test-lp/atoken-transfer.spec.ts rename to test-suites/test-amm/atoken-transfer.spec.ts index 9d1b8359..0290f941 100644 --- a/test-suites/test-lp/atoken-transfer.spec.ts +++ b/test-suites/test-amm/atoken-transfer.spec.ts @@ -4,7 +4,7 @@ import { expect } from 'chai'; import { ethers } from 'ethers'; import { RateMode, ProtocolErrors } from '../../helpers/types'; import { makeSuite, TestEnv } from './helpers/make-suite'; -import { CommonsConfig } from '../../markets/lp/commons'; +import { CommonsConfig } from '../../markets/amm/commons'; const AAVE_REFERRAL = CommonsConfig.ProtocolGlobalParams.AaveReferral; diff --git a/test-suites/test-lp/configurator.spec.ts b/test-suites/test-amm/configurator.spec.ts similarity index 99% rename from test-suites/test-lp/configurator.spec.ts rename to test-suites/test-amm/configurator.spec.ts index f4557791..e4e3f4fa 100644 --- a/test-suites/test-lp/configurator.spec.ts +++ b/test-suites/test-amm/configurator.spec.ts @@ -2,7 +2,7 @@ import { TestEnv, makeSuite } from './helpers/make-suite'; import { APPROVAL_AMOUNT_LENDING_POOL, RAY } from '../../helpers/constants'; import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; import { ProtocolErrors } from '../../helpers/types'; -import { strategyWETH } from '../../markets/lp/reservesConfigs'; +import { strategyWETH } from '../../markets/amm/reservesConfigs'; const { expect } = require('chai'); diff --git a/test-suites/test-lp/delegation-aware-atoken.spec.ts b/test-suites/test-amm/delegation-aware-atoken.spec.ts similarity index 96% rename from test-suites/test-lp/delegation-aware-atoken.spec.ts rename to test-suites/test-amm/delegation-aware-atoken.spec.ts index aeaf4499..73ca6883 100644 --- a/test-suites/test-lp/delegation-aware-atoken.spec.ts +++ b/test-suites/test-amm/delegation-aware-atoken.spec.ts @@ -20,7 +20,7 @@ import { import { DelegationAwareATokenFactory } from '../../types'; import { DelegationAwareAToken } from '../../types/DelegationAwareAToken'; import { MintableDelegationERC20 } from '../../types/MintableDelegationERC20'; -import LpConfig from '../../markets/lp'; +import AmmConfig from '../../markets/amm'; const { parseEther } = ethers.utils; @@ -35,7 +35,7 @@ makeSuite('AToken: underlying delegation', (testEnv: TestEnv) => { delegationERC20 = await deployMintableDelegationERC20(['DEL', 'DEL', '18']); delegationAToken = await deployDelegationAwareAToken( - [pool.address, delegationERC20.address, await getTreasuryAddress(LpConfig), ZERO_ADDRESS, 'aDEL', 'aDEL'], + [pool.address, delegationERC20.address, await getTreasuryAddress(AmmConfig), ZERO_ADDRESS, 'aDEL', 'aDEL'], false ); diff --git a/test-suites/test-lp/flashloan.spec.ts b/test-suites/test-amm/flashloan.spec.ts similarity index 100% rename from test-suites/test-lp/flashloan.spec.ts rename to test-suites/test-amm/flashloan.spec.ts diff --git a/test-suites/test-lp/helpers/actions.ts b/test-suites/test-amm/helpers/actions.ts similarity index 100% rename from test-suites/test-lp/helpers/actions.ts rename to test-suites/test-amm/helpers/actions.ts diff --git a/test-suites/test-lp/helpers/almost-equal.ts b/test-suites/test-amm/helpers/almost-equal.ts similarity index 100% rename from test-suites/test-lp/helpers/almost-equal.ts rename to test-suites/test-amm/helpers/almost-equal.ts diff --git a/test-suites/test-lp/helpers/make-suite.ts b/test-suites/test-amm/helpers/make-suite.ts similarity index 98% rename from test-suites/test-lp/helpers/make-suite.ts rename to test-suites/test-amm/helpers/make-suite.ts index c65f0df0..71d96bf5 100644 --- a/test-suites/test-lp/helpers/make-suite.ts +++ b/test-suites/test-amm/helpers/make-suite.ts @@ -36,7 +36,7 @@ import { getParamPerNetwork } from '../../../helpers/contracts-helpers'; import { WETH9Mocked } from '../../../types/WETH9Mocked'; import { WETHGateway } from '../../../types/WETHGateway'; import { solidity } from 'ethereum-waffle'; -import { lpConfig } from '../../../markets/lp'; +import { AmmConfig } from '../../../markets/amm'; import { FlashLiquidationAdapter } from '../../../types'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { usingTenderly } from '../../../helpers/tenderly-utils'; @@ -118,7 +118,7 @@ export async function initializeMakeSuite() { if (process.env.MAINNET_FORK === 'true') { testEnv.registry = await getLendingPoolAddressesProviderRegistry( - getParamPerNetwork(lpConfig.ProviderRegistry, eEthereumNetwork.main) + getParamPerNetwork(AmmConfig.ProviderRegistry, eEthereumNetwork.main) ); } else { testEnv.registry = await getLendingPoolAddressesProviderRegistry(); diff --git a/test-suites/test-lp/helpers/scenario-engine.ts b/test-suites/test-amm/helpers/scenario-engine.ts similarity index 100% rename from test-suites/test-lp/helpers/scenario-engine.ts rename to test-suites/test-amm/helpers/scenario-engine.ts diff --git a/test-suites/test-lp/helpers/scenarios/borrow-negatives.json b/test-suites/test-amm/helpers/scenarios/borrow-negatives.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/borrow-negatives.json rename to test-suites/test-amm/helpers/scenarios/borrow-negatives.json diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json b/test-suites/test-amm/helpers/scenarios/borrow-repay-stable.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json rename to test-suites/test-amm/helpers/scenarios/borrow-repay-stable.json diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json b/test-suites/test-amm/helpers/scenarios/borrow-repay-variable.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json rename to test-suites/test-amm/helpers/scenarios/borrow-repay-variable.json diff --git a/test-suites/test-lp/helpers/scenarios/credit-delegation.json b/test-suites/test-amm/helpers/scenarios/credit-delegation.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/credit-delegation.json rename to test-suites/test-amm/helpers/scenarios/credit-delegation.json diff --git a/test-suites/test-lp/helpers/scenarios/deposit.json b/test-suites/test-amm/helpers/scenarios/deposit.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/deposit.json rename to test-suites/test-amm/helpers/scenarios/deposit.json diff --git a/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json b/test-suites/test-amm/helpers/scenarios/rebalance-stable-rate.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json rename to test-suites/test-amm/helpers/scenarios/rebalance-stable-rate.json diff --git a/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json b/test-suites/test-amm/helpers/scenarios/set-use-as-collateral.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json rename to test-suites/test-amm/helpers/scenarios/set-use-as-collateral.json diff --git a/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json b/test-suites/test-amm/helpers/scenarios/swap-rate-mode.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/swap-rate-mode.json rename to test-suites/test-amm/helpers/scenarios/swap-rate-mode.json diff --git a/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json b/test-suites/test-amm/helpers/scenarios/withdraw-negatives.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/withdraw-negatives.json rename to test-suites/test-amm/helpers/scenarios/withdraw-negatives.json diff --git a/test-suites/test-lp/helpers/scenarios/withdraw.json b/test-suites/test-amm/helpers/scenarios/withdraw.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/withdraw.json rename to test-suites/test-amm/helpers/scenarios/withdraw.json diff --git a/test-suites/test-lp/helpers/utils/calculations.ts b/test-suites/test-amm/helpers/utils/calculations.ts similarity index 100% rename from test-suites/test-lp/helpers/utils/calculations.ts rename to test-suites/test-amm/helpers/utils/calculations.ts diff --git a/test-suites/test-lp/helpers/utils/helpers.ts b/test-suites/test-amm/helpers/utils/helpers.ts similarity index 100% rename from test-suites/test-lp/helpers/utils/helpers.ts rename to test-suites/test-amm/helpers/utils/helpers.ts diff --git a/test-suites/test-lp/helpers/utils/interfaces/index.ts b/test-suites/test-amm/helpers/utils/interfaces/index.ts similarity index 100% rename from test-suites/test-lp/helpers/utils/interfaces/index.ts rename to test-suites/test-amm/helpers/utils/interfaces/index.ts diff --git a/test-suites/test-lp/helpers/utils/math.ts b/test-suites/test-amm/helpers/utils/math.ts similarity index 100% rename from test-suites/test-lp/helpers/utils/math.ts rename to test-suites/test-amm/helpers/utils/math.ts diff --git a/test-suites/test-lp/lending-pool-addresses-provider.spec.ts b/test-suites/test-amm/lending-pool-addresses-provider.spec.ts similarity index 100% rename from test-suites/test-lp/lending-pool-addresses-provider.spec.ts rename to test-suites/test-amm/lending-pool-addresses-provider.spec.ts diff --git a/test-suites/test-lp/liquidation-atoken.spec.ts b/test-suites/test-amm/liquidation-atoken.spec.ts similarity index 100% rename from test-suites/test-lp/liquidation-atoken.spec.ts rename to test-suites/test-amm/liquidation-atoken.spec.ts diff --git a/test-suites/test-lp/liquidation-underlying.spec.ts b/test-suites/test-amm/liquidation-underlying.spec.ts similarity index 99% rename from test-suites/test-lp/liquidation-underlying.spec.ts rename to test-suites/test-amm/liquidation-underlying.spec.ts index 7bc78dad..e44a2d80 100644 --- a/test-suites/test-lp/liquidation-underlying.spec.ts +++ b/test-suites/test-amm/liquidation-underlying.spec.ts @@ -7,7 +7,7 @@ import { makeSuite } from './helpers/make-suite'; import { ProtocolErrors, RateMode } from '../../helpers/types'; import { calcExpectedVariableDebtTokenBalance } from './helpers/utils/calculations'; import { getReserveData, getUserData } from './helpers/utils/helpers'; -import { CommonsConfig } from '../../markets/lp/commons'; +import { CommonsConfig } from '../../markets/amm/commons'; import { parseEther } from 'ethers/lib/utils'; diff --git a/test-suites/test-lp/mainnet/check-list.spec.ts b/test-suites/test-amm/mainnet/check-list.spec.ts similarity index 100% rename from test-suites/test-lp/mainnet/check-list.spec.ts rename to test-suites/test-amm/mainnet/check-list.spec.ts diff --git a/test-suites/test-lp/pausable-functions.spec.ts b/test-suites/test-amm/pausable-functions.spec.ts similarity index 100% rename from test-suites/test-lp/pausable-functions.spec.ts rename to test-suites/test-amm/pausable-functions.spec.ts diff --git a/test-suites/test-lp/pool-modifiers.spec.ts b/test-suites/test-amm/pool-modifiers.spec.ts similarity index 100% rename from test-suites/test-lp/pool-modifiers.spec.ts rename to test-suites/test-amm/pool-modifiers.spec.ts diff --git a/test-suites/test-lp/rate-strategy.spec.ts b/test-suites/test-amm/rate-strategy.spec.ts similarity index 100% rename from test-suites/test-lp/rate-strategy.spec.ts rename to test-suites/test-amm/rate-strategy.spec.ts diff --git a/test-suites/test-lp/scenario.spec.ts b/test-suites/test-amm/scenario.spec.ts similarity index 93% rename from test-suites/test-lp/scenario.spec.ts rename to test-suites/test-amm/scenario.spec.ts index 99bed044..f9c4d78b 100644 --- a/test-suites/test-lp/scenario.spec.ts +++ b/test-suites/test-amm/scenario.spec.ts @@ -8,7 +8,7 @@ import { getReservesConfigByPool } from '../../helpers/configuration'; import { AavePools, iLpPoolAssets, IReserveParams } from '../../helpers/types'; import { executeStory } from './helpers/scenario-engine'; -const scenarioFolder = './test-suites/test-lp/helpers/scenarios/'; +const scenarioFolder = './test-suites/test-amm/helpers/scenarios/'; const selectedScenarios: string[] = []; @@ -25,7 +25,7 @@ fs.readdirSync(scenarioFolder).forEach((file) => { actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage calculationsConfiguration.reservesParams = >( - getReservesConfigByPool(AavePools.lp) + getReservesConfigByPool(AavePools.amm) ); }); after('Reset', () => { diff --git a/test-suites/test-lp/stable-rate-economy.spec.ts b/test-suites/test-amm/stable-rate-economy.spec.ts similarity index 100% rename from test-suites/test-lp/stable-rate-economy.spec.ts rename to test-suites/test-amm/stable-rate-economy.spec.ts diff --git a/test-suites/test-lp/stable-token.spec.ts b/test-suites/test-amm/stable-token.spec.ts similarity index 100% rename from test-suites/test-lp/stable-token.spec.ts rename to test-suites/test-amm/stable-token.spec.ts diff --git a/test-suites/test-lp/subgraph-scenarios.spec.ts b/test-suites/test-amm/subgraph-scenarios.spec.ts similarity index 96% rename from test-suites/test-lp/subgraph-scenarios.spec.ts rename to test-suites/test-amm/subgraph-scenarios.spec.ts index 24e119f1..a622eb34 100644 --- a/test-suites/test-lp/subgraph-scenarios.spec.ts +++ b/test-suites/test-amm/subgraph-scenarios.spec.ts @@ -19,7 +19,7 @@ makeSuite('Subgraph scenario tests', async (testEnv) => { actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage calculationsConfiguration.reservesParams = >( - getReservesConfigByPool(AavePools.lp) + getReservesConfigByPool(AavePools.amm) ); }); after('Reset', () => { diff --git a/test-suites/test-lp/uniswapAdapters.base.spec.ts b/test-suites/test-amm/uniswapAdapters.base.spec.ts similarity index 100% rename from test-suites/test-lp/uniswapAdapters.base.spec.ts rename to test-suites/test-amm/uniswapAdapters.base.spec.ts diff --git a/test-suites/test-lp/uniswapAdapters.flashLiquidation.spec.ts b/test-suites/test-amm/uniswapAdapters.flashLiquidation.spec.ts similarity index 100% rename from test-suites/test-lp/uniswapAdapters.flashLiquidation.spec.ts rename to test-suites/test-amm/uniswapAdapters.flashLiquidation.spec.ts diff --git a/test-suites/test-lp/uniswapAdapters.liquiditySwap.spec.ts b/test-suites/test-amm/uniswapAdapters.liquiditySwap.spec.ts similarity index 100% rename from test-suites/test-lp/uniswapAdapters.liquiditySwap.spec.ts rename to test-suites/test-amm/uniswapAdapters.liquiditySwap.spec.ts diff --git a/test-suites/test-lp/uniswapAdapters.repay.spec.ts b/test-suites/test-amm/uniswapAdapters.repay.spec.ts similarity index 100% rename from test-suites/test-lp/uniswapAdapters.repay.spec.ts rename to test-suites/test-amm/uniswapAdapters.repay.spec.ts diff --git a/test-suites/test-lp/upgradeability.spec.ts b/test-suites/test-amm/upgradeability.spec.ts similarity index 100% rename from test-suites/test-lp/upgradeability.spec.ts rename to test-suites/test-amm/upgradeability.spec.ts diff --git a/test-suites/test-lp/variable-debt-token.spec.ts b/test-suites/test-amm/variable-debt-token.spec.ts similarity index 100% rename from test-suites/test-lp/variable-debt-token.spec.ts rename to test-suites/test-amm/variable-debt-token.spec.ts diff --git a/test-suites/test-lp/weth-gateway.spec.ts b/test-suites/test-amm/weth-gateway.spec.ts similarity index 100% rename from test-suites/test-lp/weth-gateway.spec.ts rename to test-suites/test-amm/weth-gateway.spec.ts From 68447a58371e3c164c9df0653476aebfcc6385e4 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 22 Feb 2021 22:25:48 -0500 Subject: [PATCH 147/219] Updated to reuse LendingPool & Configurator if possible --- helpers/types.ts | 2 ++ markets/aave/commons.ts | 18 +++++++++++++ markets/amm/commons.ts | 18 +++++++++++++ tasks/full/2_lending_pool.ts | 43 +++++++++++++++++++++----------- tasks/full/6-initialize.ts | 7 +++--- tasks/migrations/aave.mainnet.ts | 2 +- tasks/migrations/amm.mainnet.ts | 2 +- 7 files changed, 73 insertions(+), 19 deletions(-) diff --git a/helpers/types.ts b/helpers/types.ts index 3a3f9a99..4f7c739b 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -428,6 +428,8 @@ export interface ICommonConfiguration { ProviderRegistry: iParamsPerNetwork; ProviderRegistryOwner: iParamsPerNetwork; LendingPoolCollateralManager: iParamsPerNetwork; + LendingPoolConfigurator: iParamsPerNetwork; + LendingPool: iParamsPerNetwork; LendingRateOracleRatesCommon: iMultiPoolsAssets; LendingRateOracle: iParamsPerNetwork; TokenDistributor: iParamsPerNetwork; diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index 642535d1..115f9372 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -190,6 +190,24 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', }, + LendingPoolConfigurator: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, + LendingPool: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, WethGateway: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', diff --git a/markets/amm/commons.ts b/markets/amm/commons.ts index e02676ae..caacf04a 100644 --- a/markets/amm/commons.ts +++ b/markets/amm/commons.ts @@ -199,6 +199,24 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', }, + LendingPoolConfigurator: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '0x36eB31800aa67a9c50df1d56EE01981A6E14Cce5', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, + LendingPool: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '0x78142De7a1930412E9e50dEB3b80dB284c2dFa3A', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, WethGateway: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', diff --git a/tasks/full/2_lending_pool.ts b/tasks/full/2_lending_pool.ts index db0daabb..fd6e1352 100644 --- a/tasks/full/2_lending_pool.ts +++ b/tasks/full/2_lending_pool.ts @@ -1,45 +1,60 @@ import { task } from 'hardhat/config'; -import { insertContractAddressInDb } from '../../helpers/contracts-helpers'; +import { getParamPerNetwork, 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'; +import { eContractid, eEthereumNetwork } from '../../helpers/types'; +import { notFalsyOrZeroAddress, waitForTx } from '../../helpers/misc-utils'; import { getLendingPoolAddressesProvider, getLendingPool, getLendingPoolConfiguratorProxy, } from '../../helpers/contracts-getters'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { loadPoolConfig, ConfigNames } from '../../helpers/configuration'; task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({ verify }, DRE: HardhatRuntimeEnvironment) => { + .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) + .setAction(async ({ verify, pool }, DRE: HardhatRuntimeEnvironment) => { try { await DRE.run('set-DRE'); - + const network = DRE.network.name; + const poolConfig = loadPoolConfig(pool) const addressesProvider = await getLendingPoolAddressesProvider(); + + const { LendingPool, LendingPoolConfigurator } = poolConfig; - // Deploy lending pool - const lendingPoolImpl = await deployLendingPool(verify); - - // Set lending pool impl to address provider - await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address)); + // Reuse/deploy lending pool implementation + let lendingPoolImplAddress = getParamPerNetwork(LendingPool, network) + if (!notFalsyOrZeroAddress(lendingPoolImplAddress)) { + console.log("\tDeploying new lending pool implementation & libraries..."); + const lendingPoolImpl = await deployLendingPool(verify); + lendingPoolImplAddress = lendingPoolImpl.address; + } + console.log("\tSetting lending pool implementation with address:" , lendingPoolImplAddress); + // Set lending pool impl to Address provider + await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImplAddress)); const address = await addressesProvider.getLendingPool(); const lendingPoolProxy = await getLendingPool(address); await insertContractAddressInDb(eContractid.LendingPool, lendingPoolProxy.address); - // Deploy lending pool configurator - const lendingPoolConfiguratorImpl = await deployLendingPoolConfigurator(verify); - + // Reuse/deploy lending pool configurator + let lendingPoolConfiguratorImplAddress = getParamPerNetwork(LendingPoolConfigurator, network); //await deployLendingPoolConfigurator(verify); + if (!notFalsyOrZeroAddress(lendingPoolConfiguratorImplAddress)) { + console.log("\tDeploying new configurator implementation..."); + const lendingPoolConfiguratorImpl = await deployLendingPoolConfigurator(verify); + lendingPoolConfiguratorImplAddress = lendingPoolConfiguratorImpl.address; + } + console.log("\tSetting lending pool configurator implementation with address:" , lendingPoolConfiguratorImplAddress); // Set lending pool conf impl to Address Provider await waitForTx( - await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImpl.address) + await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImplAddress) ); const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy( diff --git a/tasks/full/6-initialize.ts b/tasks/full/6-initialize.ts index 1b949241..b5ee3aea 100644 --- a/tasks/full/6-initialize.ts +++ b/tasks/full/6-initialize.ts @@ -14,7 +14,7 @@ import { } from '../../helpers/configuration'; import { getWETHGateway } from '../../helpers/contracts-getters'; import { eEthereumNetwork, ICommonConfiguration } from '../../helpers/types'; -import { waitForTx } from '../../helpers/misc-utils'; +import { notFalsyOrZeroAddress, waitForTx } from '../../helpers/misc-utils'; import { initReservesByHelper, configureReservesByHelper } from '../../helpers/init-helpers'; import { exit } from 'process'; import { @@ -73,12 +73,13 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') LendingPoolCollateralManager, network ); - if (!collateralManagerAddress) { + if (!notFalsyOrZeroAddress(collateralManagerAddress)) { const collateralManager = await deployLendingPoolCollateralManager(verify); collateralManagerAddress = collateralManager.address; } // Seems unnecessary to register the collateral manager in the JSON db + console.log("\tSetting lending pool collateral manager implementation with address", collateralManagerAddress); await waitForTx( await addressesProvider.setLendingPoolCollateralManager(collateralManagerAddress) ); @@ -88,7 +89,7 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const lendingPoolAddress = await addressesProvider.getLendingPool(); let gateWay = getParamPerNetwork(WethGateway, network); - if (gateWay == '') { + if (!notFalsyOrZeroAddress(gateWay)) { gateWay = (await getWETHGateway()).address; } await authorizeWETHGateway(gateWay, lendingPoolAddress); diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index fe05938d..19649262 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -21,7 +21,7 @@ task('aave:mainnet', 'Deploy development enviroment') await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); console.log('2. Deploy lending pool'); - await DRE.run('full: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 }); diff --git a/tasks/migrations/amm.mainnet.ts b/tasks/migrations/amm.mainnet.ts index 73efeebe..3d0e6c8b 100644 --- a/tasks/migrations/amm.mainnet.ts +++ b/tasks/migrations/amm.mainnet.ts @@ -21,7 +21,7 @@ task('amm:mainnet', 'Deploy development enviroment') await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); console.log('2. Deploy lending pool'); - await DRE.run('full: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 }); From 82c09164e10d55fd4a00aa6ade61ddc9b8be0317 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 22 Feb 2021 22:25:58 -0500 Subject: [PATCH 148/219] Fixed & tested etherscan verification (on Kovan) --- tasks/verifications/1_general.ts | 44 +++++++++++++++++++++++--------- tasks/verifications/2_tokens.ts | 13 ++++++++-- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/tasks/verifications/1_general.ts b/tasks/verifications/1_general.ts index 89a54d0d..80a76162 100644 --- a/tasks/verifications/1_general.ts +++ b/tasks/verifications/1_general.ts @@ -27,7 +27,7 @@ import { verifyContract } from '../../helpers/etherscan-verification'; import { notFalsyOrZeroAddress } from '../../helpers/misc-utils'; import { eEthereumNetwork, ICommonConfiguration } from '../../helpers/types'; -task('verify:general', 'Deploy oracles for dev enviroment') +task('verify:general', 'Verify contracts at Etherscan') .addFlag('all', 'Verify all contracts at Etherscan') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ all, pool }, localDRE) => { @@ -39,6 +39,10 @@ task('verify:general', 'Deploy oracles for dev enviroment') ReservesConfig, ProviderRegistry, MarketId, + LendingPoolCollateralManager, + LendingPoolConfigurator, + LendingPool, + WethGateway, } = poolConfig as ICommonConfiguration; const treasuryAddress = await getTreasuryAddress(poolConfig); @@ -47,17 +51,33 @@ task('verify:general', 'Deploy oracles for dev enviroment') const addressesProviderRegistry = notFalsyOrZeroAddress(registryAddress) ? await getLendingPoolAddressesProviderRegistry(registryAddress) : await getLendingPoolAddressesProviderRegistry(); - const lendingPoolProxy = await getLendingPool(); - const lendingPoolConfigurator = await getLendingPoolConfiguratorProxy(); - const lendingPoolCollateralManager = await getLendingPoolCollateralManager(); + const lendingPoolAddress = await addressesProvider.getLendingPool(); + const lendingPoolConfiguratorAddress = await addressesProvider.getLendingPoolConfigurator();//getLendingPoolConfiguratorProxy(); + const lendingPoolCollateralManagerAddress = await addressesProvider.getLendingPoolCollateralManager(); if (all) { - const lendingPoolImpl = await getLendingPoolImpl(); - const lendingPoolConfiguratorImpl = await getLendingPoolConfiguratorImpl(); - const lendingPoolCollateralManagerImpl = await getLendingPoolCollateralManagerImpl(); + const lendingPoolImplAddress = getParamPerNetwork(LendingPool, network); + const lendingPoolImpl = notFalsyOrZeroAddress(lendingPoolImplAddress) + ? await getLendingPoolImpl(lendingPoolImplAddress) + : await getLendingPoolImpl(); + + const lendingPoolConfiguratorImplAddress = getParamPerNetwork(LendingPoolConfigurator, network); + const lendingPoolConfiguratorImpl = notFalsyOrZeroAddress(lendingPoolConfiguratorImplAddress) + ? await getLendingPoolConfiguratorImpl(lendingPoolConfiguratorImplAddress) + : await getLendingPoolConfiguratorImpl(); + + const lendingPoolCollateralManagerImplAddress = getParamPerNetwork(LendingPoolCollateralManager, network); + const lendingPoolCollateralManagerImpl = notFalsyOrZeroAddress(lendingPoolCollateralManagerImplAddress) + ? await getLendingPoolCollateralManagerImpl(lendingPoolCollateralManagerImplAddress) + : await getLendingPoolCollateralManagerImpl(); + const dataProvider = await getAaveProtocolDataProvider(); const walletProvider = await getWalletProvider(); - const wethGateway = await getWETHGateway(); + + const wethGatewayAddress = getParamPerNetwork(WethGateway, network); + const wethGateway = notFalsyOrZeroAddress(wethGatewayAddress) + ? await getWETHGateway(wethGatewayAddress) + : await getWETHGateway(); // Address Provider console.log('\n- Verifying address provider...\n'); @@ -93,15 +113,15 @@ task('verify:general', 'Deploy oracles for dev enviroment') } // Lending Pool proxy console.log('\n- Verifying Lending Pool Proxy...\n'); - await verifyContract(lendingPoolProxy.address, [addressesProvider.address]); + await verifyContract(lendingPoolAddress, [addressesProvider.address]); // LendingPool Conf proxy console.log('\n- Verifying Lending Pool Configurator Proxy...\n'); - await verifyContract(lendingPoolConfigurator.address, [addressesProvider.address]); + await verifyContract(lendingPoolConfiguratorAddress, [addressesProvider.address]); // Proxy collateral manager console.log('\n- Verifying Lending Pool Collateral Manager Proxy...\n'); - await verifyContract(lendingPoolCollateralManager.address, []); + await verifyContract(lendingPoolCollateralManagerAddress, []); // DelegatedAwareAToken console.log('\n- Verifying DelegatedAwareAToken...\n'); @@ -110,7 +130,7 @@ task('verify:general', 'Deploy oracles for dev enviroment') if (aUNI) { console.log('Verifying aUNI'); await verifyContract(aUNI, [ - lendingPoolProxy.address, + lendingPoolAddress, UNI, treasuryAddress, 'Aave interest bearing UNI', diff --git a/tasks/verifications/2_tokens.ts b/tasks/verifications/2_tokens.ts index 4ea86cc5..a611c275 100644 --- a/tasks/verifications/2_tokens.ts +++ b/tasks/verifications/2_tokens.ts @@ -8,6 +8,7 @@ import { import { ZERO_ADDRESS } from '../../helpers/constants'; import { getAddressById, + getFirstSigner, getLendingPool, getLendingPoolAddressesProvider, getLendingPoolConfiguratorProxy, @@ -15,6 +16,7 @@ import { import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { verifyContract } from '../../helpers/etherscan-verification'; import { eEthereumNetwork, ICommonConfiguration, IReserveParams } from '../../helpers/types'; +import { LendingPoolConfiguratorFactory, LendingPoolFactory } from '../../types'; task('verify:tokens', 'Deploy oracles for dev enviroment') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) @@ -26,8 +28,15 @@ task('verify:tokens', 'Deploy oracles for dev enviroment') const treasuryAddress = await getTreasuryAddress(poolConfig); const addressesProvider = await getLendingPoolAddressesProvider(); - const lendingPoolProxy = await getLendingPool(); - const lendingPoolConfigurator = await getLendingPoolConfiguratorProxy(); + const lendingPoolProxy = LendingPoolFactory.connect( + await addressesProvider.getLendingPool(), + await getFirstSigner() + ); + + const lendingPoolConfigurator = LendingPoolConfiguratorFactory.connect( + await addressesProvider.getLendingPoolConfigurator(), + await getFirstSigner() + ); const configs = Object.entries(ReservesConfig) as [string, IReserveParams][]; for (const entry of Object.entries(getParamPerNetwork(ReserveAssets, network))) { From 50e2828008afc48716d18749affd73ea016dfda9 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 22 Feb 2021 22:25:48 -0500 Subject: [PATCH 149/219] Updated to reuse LendingPool & Configurator if possible --- helpers/types.ts | 2 ++ markets/aave/commons.ts | 18 +++++++++++++ markets/lp/commons.ts | 18 +++++++++++++ tasks/full/2_lending_pool.ts | 43 +++++++++++++++++++++----------- tasks/full/6-initialize.ts | 7 +++--- tasks/migrations/aave.mainnet.ts | 2 +- tasks/migrations/lp.mainnet.ts | 2 +- 7 files changed, 73 insertions(+), 19 deletions(-) diff --git a/helpers/types.ts b/helpers/types.ts index 8b6b442d..d2d33b51 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -464,6 +464,8 @@ export interface ICommonConfiguration { ProviderRegistry: iParamsPerNetwork; ProviderRegistryOwner: iParamsPerNetwork; LendingPoolCollateralManager: iParamsPerNetwork; + LendingPoolConfigurator: iParamsPerNetwork; + LendingPool: iParamsPerNetwork; LendingRateOracleRatesCommon: iMultiPoolsAssets; LendingRateOracle: iParamsPerNetwork; TokenDistributor: iParamsPerNetwork; diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index da91442d..f16c9227 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -153,6 +153,24 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', }, + LendingPoolConfigurator: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, + LendingPool: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, WethGateway: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', diff --git a/markets/lp/commons.ts b/markets/lp/commons.ts index 9c7ca2ee..bce33b98 100644 --- a/markets/lp/commons.ts +++ b/markets/lp/commons.ts @@ -156,6 +156,24 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', [eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C', }, + LendingPoolConfigurator: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '0x36eB31800aa67a9c50df1d56EE01981A6E14Cce5', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, + LendingPool: { + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.kovan]: '0x78142De7a1930412E9e50dEB3b80dB284c2dFa3A', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', + [eEthereumNetwork.tenderlyMain]: '', + }, WethGateway: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', diff --git a/tasks/full/2_lending_pool.ts b/tasks/full/2_lending_pool.ts index db0daabb..fd6e1352 100644 --- a/tasks/full/2_lending_pool.ts +++ b/tasks/full/2_lending_pool.ts @@ -1,45 +1,60 @@ import { task } from 'hardhat/config'; -import { insertContractAddressInDb } from '../../helpers/contracts-helpers'; +import { getParamPerNetwork, 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'; +import { eContractid, eEthereumNetwork } from '../../helpers/types'; +import { notFalsyOrZeroAddress, waitForTx } from '../../helpers/misc-utils'; import { getLendingPoolAddressesProvider, getLendingPool, getLendingPoolConfiguratorProxy, } from '../../helpers/contracts-getters'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { loadPoolConfig, ConfigNames } from '../../helpers/configuration'; task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({ verify }, DRE: HardhatRuntimeEnvironment) => { + .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) + .setAction(async ({ verify, pool }, DRE: HardhatRuntimeEnvironment) => { try { await DRE.run('set-DRE'); - + const network = DRE.network.name; + const poolConfig = loadPoolConfig(pool) const addressesProvider = await getLendingPoolAddressesProvider(); + + const { LendingPool, LendingPoolConfigurator } = poolConfig; - // Deploy lending pool - const lendingPoolImpl = await deployLendingPool(verify); - - // Set lending pool impl to address provider - await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address)); + // Reuse/deploy lending pool implementation + let lendingPoolImplAddress = getParamPerNetwork(LendingPool, network) + if (!notFalsyOrZeroAddress(lendingPoolImplAddress)) { + console.log("\tDeploying new lending pool implementation & libraries..."); + const lendingPoolImpl = await deployLendingPool(verify); + lendingPoolImplAddress = lendingPoolImpl.address; + } + console.log("\tSetting lending pool implementation with address:" , lendingPoolImplAddress); + // Set lending pool impl to Address provider + await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImplAddress)); const address = await addressesProvider.getLendingPool(); const lendingPoolProxy = await getLendingPool(address); await insertContractAddressInDb(eContractid.LendingPool, lendingPoolProxy.address); - // Deploy lending pool configurator - const lendingPoolConfiguratorImpl = await deployLendingPoolConfigurator(verify); - + // Reuse/deploy lending pool configurator + let lendingPoolConfiguratorImplAddress = getParamPerNetwork(LendingPoolConfigurator, network); //await deployLendingPoolConfigurator(verify); + if (!notFalsyOrZeroAddress(lendingPoolConfiguratorImplAddress)) { + console.log("\tDeploying new configurator implementation..."); + const lendingPoolConfiguratorImpl = await deployLendingPoolConfigurator(verify); + lendingPoolConfiguratorImplAddress = lendingPoolConfiguratorImpl.address; + } + console.log("\tSetting lending pool configurator implementation with address:" , lendingPoolConfiguratorImplAddress); // Set lending pool conf impl to Address Provider await waitForTx( - await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImpl.address) + await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImplAddress) ); const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy( diff --git a/tasks/full/6-initialize.ts b/tasks/full/6-initialize.ts index 1b949241..b5ee3aea 100644 --- a/tasks/full/6-initialize.ts +++ b/tasks/full/6-initialize.ts @@ -14,7 +14,7 @@ import { } from '../../helpers/configuration'; import { getWETHGateway } from '../../helpers/contracts-getters'; import { eEthereumNetwork, ICommonConfiguration } from '../../helpers/types'; -import { waitForTx } from '../../helpers/misc-utils'; +import { notFalsyOrZeroAddress, waitForTx } from '../../helpers/misc-utils'; import { initReservesByHelper, configureReservesByHelper } from '../../helpers/init-helpers'; import { exit } from 'process'; import { @@ -73,12 +73,13 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') LendingPoolCollateralManager, network ); - if (!collateralManagerAddress) { + if (!notFalsyOrZeroAddress(collateralManagerAddress)) { const collateralManager = await deployLendingPoolCollateralManager(verify); collateralManagerAddress = collateralManager.address; } // Seems unnecessary to register the collateral manager in the JSON db + console.log("\tSetting lending pool collateral manager implementation with address", collateralManagerAddress); await waitForTx( await addressesProvider.setLendingPoolCollateralManager(collateralManagerAddress) ); @@ -88,7 +89,7 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const lendingPoolAddress = await addressesProvider.getLendingPool(); let gateWay = getParamPerNetwork(WethGateway, network); - if (gateWay == '') { + if (!notFalsyOrZeroAddress(gateWay)) { gateWay = (await getWETHGateway()).address; } await authorizeWETHGateway(gateWay, lendingPoolAddress); diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index fe05938d..19649262 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -21,7 +21,7 @@ task('aave:mainnet', 'Deploy development enviroment') await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); console.log('2. Deploy lending pool'); - await DRE.run('full: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 }); diff --git a/tasks/migrations/lp.mainnet.ts b/tasks/migrations/lp.mainnet.ts index 4faea738..97a47ffa 100644 --- a/tasks/migrations/lp.mainnet.ts +++ b/tasks/migrations/lp.mainnet.ts @@ -21,7 +21,7 @@ task('lp:mainnet', 'Deploy development enviroment') await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); console.log('2. Deploy lending pool'); - await DRE.run('full: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 }); From 599c2759f16d09e480be69c889b543cbf998b763 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 22 Feb 2021 22:25:58 -0500 Subject: [PATCH 150/219] Fixed & tested etherscan verification (on Kovan) --- tasks/verifications/1_general.ts | 44 +++++++++++++++++++++++--------- tasks/verifications/2_tokens.ts | 13 ++++++++-- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/tasks/verifications/1_general.ts b/tasks/verifications/1_general.ts index 89a54d0d..80a76162 100644 --- a/tasks/verifications/1_general.ts +++ b/tasks/verifications/1_general.ts @@ -27,7 +27,7 @@ import { verifyContract } from '../../helpers/etherscan-verification'; import { notFalsyOrZeroAddress } from '../../helpers/misc-utils'; import { eEthereumNetwork, ICommonConfiguration } from '../../helpers/types'; -task('verify:general', 'Deploy oracles for dev enviroment') +task('verify:general', 'Verify contracts at Etherscan') .addFlag('all', 'Verify all contracts at Etherscan') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ all, pool }, localDRE) => { @@ -39,6 +39,10 @@ task('verify:general', 'Deploy oracles for dev enviroment') ReservesConfig, ProviderRegistry, MarketId, + LendingPoolCollateralManager, + LendingPoolConfigurator, + LendingPool, + WethGateway, } = poolConfig as ICommonConfiguration; const treasuryAddress = await getTreasuryAddress(poolConfig); @@ -47,17 +51,33 @@ task('verify:general', 'Deploy oracles for dev enviroment') const addressesProviderRegistry = notFalsyOrZeroAddress(registryAddress) ? await getLendingPoolAddressesProviderRegistry(registryAddress) : await getLendingPoolAddressesProviderRegistry(); - const lendingPoolProxy = await getLendingPool(); - const lendingPoolConfigurator = await getLendingPoolConfiguratorProxy(); - const lendingPoolCollateralManager = await getLendingPoolCollateralManager(); + const lendingPoolAddress = await addressesProvider.getLendingPool(); + const lendingPoolConfiguratorAddress = await addressesProvider.getLendingPoolConfigurator();//getLendingPoolConfiguratorProxy(); + const lendingPoolCollateralManagerAddress = await addressesProvider.getLendingPoolCollateralManager(); if (all) { - const lendingPoolImpl = await getLendingPoolImpl(); - const lendingPoolConfiguratorImpl = await getLendingPoolConfiguratorImpl(); - const lendingPoolCollateralManagerImpl = await getLendingPoolCollateralManagerImpl(); + const lendingPoolImplAddress = getParamPerNetwork(LendingPool, network); + const lendingPoolImpl = notFalsyOrZeroAddress(lendingPoolImplAddress) + ? await getLendingPoolImpl(lendingPoolImplAddress) + : await getLendingPoolImpl(); + + const lendingPoolConfiguratorImplAddress = getParamPerNetwork(LendingPoolConfigurator, network); + const lendingPoolConfiguratorImpl = notFalsyOrZeroAddress(lendingPoolConfiguratorImplAddress) + ? await getLendingPoolConfiguratorImpl(lendingPoolConfiguratorImplAddress) + : await getLendingPoolConfiguratorImpl(); + + const lendingPoolCollateralManagerImplAddress = getParamPerNetwork(LendingPoolCollateralManager, network); + const lendingPoolCollateralManagerImpl = notFalsyOrZeroAddress(lendingPoolCollateralManagerImplAddress) + ? await getLendingPoolCollateralManagerImpl(lendingPoolCollateralManagerImplAddress) + : await getLendingPoolCollateralManagerImpl(); + const dataProvider = await getAaveProtocolDataProvider(); const walletProvider = await getWalletProvider(); - const wethGateway = await getWETHGateway(); + + const wethGatewayAddress = getParamPerNetwork(WethGateway, network); + const wethGateway = notFalsyOrZeroAddress(wethGatewayAddress) + ? await getWETHGateway(wethGatewayAddress) + : await getWETHGateway(); // Address Provider console.log('\n- Verifying address provider...\n'); @@ -93,15 +113,15 @@ task('verify:general', 'Deploy oracles for dev enviroment') } // Lending Pool proxy console.log('\n- Verifying Lending Pool Proxy...\n'); - await verifyContract(lendingPoolProxy.address, [addressesProvider.address]); + await verifyContract(lendingPoolAddress, [addressesProvider.address]); // LendingPool Conf proxy console.log('\n- Verifying Lending Pool Configurator Proxy...\n'); - await verifyContract(lendingPoolConfigurator.address, [addressesProvider.address]); + await verifyContract(lendingPoolConfiguratorAddress, [addressesProvider.address]); // Proxy collateral manager console.log('\n- Verifying Lending Pool Collateral Manager Proxy...\n'); - await verifyContract(lendingPoolCollateralManager.address, []); + await verifyContract(lendingPoolCollateralManagerAddress, []); // DelegatedAwareAToken console.log('\n- Verifying DelegatedAwareAToken...\n'); @@ -110,7 +130,7 @@ task('verify:general', 'Deploy oracles for dev enviroment') if (aUNI) { console.log('Verifying aUNI'); await verifyContract(aUNI, [ - lendingPoolProxy.address, + lendingPoolAddress, UNI, treasuryAddress, 'Aave interest bearing UNI', diff --git a/tasks/verifications/2_tokens.ts b/tasks/verifications/2_tokens.ts index 4ea86cc5..a611c275 100644 --- a/tasks/verifications/2_tokens.ts +++ b/tasks/verifications/2_tokens.ts @@ -8,6 +8,7 @@ import { import { ZERO_ADDRESS } from '../../helpers/constants'; import { getAddressById, + getFirstSigner, getLendingPool, getLendingPoolAddressesProvider, getLendingPoolConfiguratorProxy, @@ -15,6 +16,7 @@ import { import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { verifyContract } from '../../helpers/etherscan-verification'; import { eEthereumNetwork, ICommonConfiguration, IReserveParams } from '../../helpers/types'; +import { LendingPoolConfiguratorFactory, LendingPoolFactory } from '../../types'; task('verify:tokens', 'Deploy oracles for dev enviroment') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) @@ -26,8 +28,15 @@ task('verify:tokens', 'Deploy oracles for dev enviroment') const treasuryAddress = await getTreasuryAddress(poolConfig); const addressesProvider = await getLendingPoolAddressesProvider(); - const lendingPoolProxy = await getLendingPool(); - const lendingPoolConfigurator = await getLendingPoolConfiguratorProxy(); + const lendingPoolProxy = LendingPoolFactory.connect( + await addressesProvider.getLendingPool(), + await getFirstSigner() + ); + + const lendingPoolConfigurator = LendingPoolConfiguratorFactory.connect( + await addressesProvider.getLendingPoolConfigurator(), + await getFirstSigner() + ); const configs = Object.entries(ReservesConfig) as [string, IReserveParams][]; for (const entry of Object.entries(getParamPerNetwork(ReserveAssets, network))) { From 029a349d903e6068f13ad9c86e247f7f7239cd62 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 23 Feb 2021 09:26:48 +0100 Subject: [PATCH 151/219] Prepared XDAI configs, updated matic with new LendingPool and LendingPoolConfigurator --- helpers/constants.ts | 1 + helpers/types.ts | 11 +++ markets/matic/commons.ts | 8 ++ markets/xdai/commons.ts | 120 ++++++++++++++++++++++++++ markets/xdai/index.ts | 41 +++++++++ markets/xdai/rateStrategies.ts | 91 +++++++++++++++++++ markets/xdai/reservesConfigs.ts | 85 ++++++++++++++++++ test-suites/test-aave/__setup.spec.ts | 1 + test-suites/test-lp/__setup.spec.ts | 1 + 9 files changed, 359 insertions(+) diff --git a/helpers/constants.ts b/helpers/constants.ts index cb66e8a1..9a223bd6 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -66,5 +66,6 @@ export const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), WMATIC: oneEther.multipliedBy('0.003620948469').toFixed(), + STAKE: oneEther.multipliedBy('0.003620948469').toFixed(), USD: '5848466240000000', }; diff --git a/helpers/types.ts b/helpers/types.ts index d2d33b51..526b2f98 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -239,6 +239,7 @@ export interface iAssetBase { UniYFIWETH: T; BptWBTCWETH: T; WMATIC: T; + STAKE: T; } export type iAssetsWithoutETH = Omit, 'ETH'>; @@ -298,6 +299,11 @@ export type iMaticPoolAssets = Pick< 'DAI' | 'USDC' | 'USDT' | 'WBTC' | 'WETH' | 'WMATIC' >; +export type iXDAIPoolAssets = Pick< + iAssetsWithoutUSD, + 'DAI' | 'USDC' | 'USDT' | 'WBTC' | 'WETH' | 'STAKE' +>; + export type iMultiPoolsAssets = iAssetCommon | iAavePoolAssets; export type iAavePoolTokens = Omit, 'ETH'>; @@ -347,6 +353,7 @@ export enum TokenContractId { UniYFIWETH = 'UniYFIWETH', BptWBTCWETH = 'BptWBTCWETH', WMATIC = 'WMATIC', + STAKE = 'STAKE', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { @@ -496,6 +503,10 @@ export interface IMaticConfiguration extends ICommonConfiguration { ReservesConfig: iMaticPoolAssets; } +export interface IXDAIConfiguration extends ICommonConfiguration { + ReservesConfig: iXDAIPoolAssets; +} + export interface ITokenAddress { [token: string]: tEthereumAddress; } diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index b92a1eb6..784f156d 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -66,6 +66,14 @@ export const CommonsConfig: ICommonConfiguration = { [ePolygonNetwork.mumbai]: undefined, [ePolygonNetwork.matic]: undefined, }, + LendingPool: { + [ePolygonNetwork.mumbai]: '', + [ePolygonNetwork.matic]: '0x15Ec48a46d2D26cf4ADf5A39123E4c75e6887fE0', + }, + LendingPoolConfigurator: { + [ePolygonNetwork.mumbai]: '', + [ePolygonNetwork.matic]: '0x268F48E09c72f6008DA50D6465a174C10167918e', + }, EmergencyAdminIndex: 1, ProviderRegistry: { [ePolygonNetwork.mumbai]: '0x569859d41499B4dDC28bfaA43915051FF0A38a6F', // TEMP diff --git a/markets/xdai/commons.ts b/markets/xdai/commons.ts index e69de29b..433d54ea 100644 --- a/markets/xdai/commons.ts +++ b/markets/xdai/commons.ts @@ -0,0 +1,120 @@ +import BigNumber from 'bignumber.js'; +import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants'; +import { ICommonConfiguration, eXDaiNetwork } from '../../helpers/types'; + +// ---------------- +// PROTOCOL GLOBAL PARAMS +// ---------------- + +export const CommonsConfig: ICommonConfiguration = { + MarketId: 'Commons', + ATokenNamePrefix: 'Aave XDAI Market', + StableDebtTokenNamePrefix: 'Aave XDAI Market stable debt', + VariableDebtTokenNamePrefix: 'Aave XDAI Market variable debt', + SymbolPrefix: 'm', + ProviderId: 0, // Overriden in index.ts + 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(), + }, + DAI: { + borrowRate: oneRay.multipliedBy(0.039).toFixed(), + }, + USDC: { + borrowRate: oneRay.multipliedBy(0.039).toFixed(), + }, + USDT: { + borrowRate: oneRay.multipliedBy(0.035).toFixed(), + }, + WBTC: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + STAKE: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), // TEMP + }, + }, + // ---------------- + // COMMON PROTOCOL ADDRESSES ACROSS POOLS + // ---------------- + + // If PoolAdmin/emergencyAdmin is set, will take priority over PoolAdminIndex/emergencyAdminIndex + PoolAdmin: { + [eXDaiNetwork.xdai]: undefined, + }, + PoolAdminIndex: 0, + EmergencyAdmin: { + [eXDaiNetwork.xdai]: undefined, + }, + EmergencyAdminIndex: 1, + ProviderRegistry: { + [eXDaiNetwork.xdai]: '', + }, + ProviderRegistryOwner: { + [eXDaiNetwork.xdai]: '', + }, + LendingPoolConfigurator: { + [eXDaiNetwork.xdai]: '0', + }, + LendingPool: { + [eXDaiNetwork.xdai]: '0', + }, + LendingRateOracle: { + [eXDaiNetwork.xdai]: '', + }, + LendingPoolCollateralManager: { + [eXDaiNetwork.xdai]: '', + }, + TokenDistributor: { + [eXDaiNetwork.xdai]: '', + }, + WethGateway: { + [eXDaiNetwork.xdai]: '', + }, + AaveOracle: { + [eXDaiNetwork.xdai]: '', + }, + FallbackOracle: { + [eXDaiNetwork.xdai]: ZERO_ADDRESS, + }, + ChainlinkAggregator: { + [eXDaiNetwork.xdai]: { + DAI: ZERO_ADDRESS, + USDC: ZERO_ADDRESS, + USDT: ZERO_ADDRESS, + WBTC: ZERO_ADDRESS, + STAKE: ZERO_ADDRESS, + }, + }, + ReserveAssets: { + [eXDaiNetwork.xdai]: {}, + }, + ReservesConfig: {}, + ATokenDomainSeparator: { + [eXDaiNetwork.xdai]: '', + }, + WETH: { + [eXDaiNetwork.xdai]: '', // DAI: xDAI is the base token, DAI is also there, We need WXDAI + }, + ReserveFactorTreasuryAddress: { + [eXDaiNetwork.xdai]: '', // TEMP + }, +}; diff --git a/markets/xdai/index.ts b/markets/xdai/index.ts index 8b137891..fadf52c8 100644 --- a/markets/xdai/index.ts +++ b/markets/xdai/index.ts @@ -1 +1,42 @@ +import { oneRay, ZERO_ADDRESS } from '../../helpers/constants'; +import { IXDAIConfiguration, eXDaiNetwork } from '../../helpers/types'; +import { CommonsConfig } from './commons'; +import { + strategyDAI, + strategyUSDC, + strategyUSDT, + strategyWBTC, + strategyWETH, + strategySTAKE, +} from './reservesConfigs'; + +// ---------------- +// POOL--SPECIFIC PARAMS +// ---------------- + +export const XDAIConfig: IXDAIConfiguration = { + ...CommonsConfig, + MarketId: 'XDAI Market', + ProviderId: 4, // Unknown? + ReservesConfig: { + DAI: strategyDAI, + USDC: strategyUSDC, + USDT: strategyUSDT, + WBTC: strategyWBTC, + WETH: strategyWETH, + STAKE: strategySTAKE, + }, + ReserveAssets: { + [eXDaiNetwork.xdai]: { + DAI: '0x44fA8E6f47987339850636F88629646662444217', + USDC: '0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83', + USDT: '0x4ECaBa5870353805a9F068101A40E0f32ed605C6', + WBTC: '0x8e5bBbb09Ed1ebdE8674Cda39A0c169401db4252', + WETH: '0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1', + STAKE: '0xb7D311E2Eb55F2f68a9440da38e7989210b9A05e' + }, + }, +}; + +export default XDAIConfig; diff --git a/markets/xdai/rateStrategies.ts b/markets/xdai/rateStrategies.ts index e69de29b..afe19b63 100644 --- a/markets/xdai/rateStrategies.ts +++ b/markets/xdai/rateStrategies.ts @@ -0,0 +1,91 @@ +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(), +} diff --git a/markets/xdai/reservesConfigs.ts b/markets/xdai/reservesConfigs.ts index e69de29b..6c90afc5 100644 --- a/markets/xdai/reservesConfigs.ts +++ b/markets/xdai/reservesConfigs.ts @@ -0,0 +1,85 @@ +// import BigNumber from 'bignumber.js'; +// import { oneRay } from '../../helpers/constants'; +import { eContractid, IReserveParams } from '../../helpers/types'; +import { + rateStrategyStableOne, + rateStrategyStableTwo, + rateStrategyStableThree, + rateStrategyWETH, + rateStrategyAAVE, + rateStrategyVolatileOne, + rateStrategyVolatileTwo, + rateStrategyVolatileThree, +} from './rateStrategies'; + +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 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 strategyWETH: IReserveParams = { + strategy: rateStrategyWETH, + baseLTVAsCollateral: '8000', + liquidationThreshold: '8250', + liquidationBonus: '10500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000' +}; + +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 strategySTAKE: IReserveParams = { + strategy: rateStrategyVolatileOne, //Temp? + baseLTVAsCollateral: '5000', + liquidationThreshold: '6500', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '2000' +}; \ No newline at end of file diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index 00935f53..c9a54f7f 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -189,6 +189,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { BptWBTCWETH: mockTokens.BptWBTCWETH.address, WMATIC: mockTokens.WMATIC.address, USD: USD_ADDRESS, + STAKE: mockTokens.STAKE.address, }, fallbackOracle ); diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-lp/__setup.spec.ts index e7515f25..d359b51e 100644 --- a/test-suites/test-lp/__setup.spec.ts +++ b/test-suites/test-lp/__setup.spec.ts @@ -188,6 +188,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { BptWBTCWETH: mockTokens.BptWBTCWETH.address, WMATIC: mockTokens.WMATIC.address, USD: USD_ADDRESS, + STAKE: mockTokens.STAKE.address, }, fallbackOracle ); From e3846332db03bd85f42034cbe4319cf14ebd424e Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 23 Feb 2021 15:42:47 +0100 Subject: [PATCH 152/219] Cleaned up more conf, getParanetwork working now. Added weth Gateway Matic --- hardhat.config.ts | 4 +- helpers/configuration.ts | 20 +-- helpers/contracts-helpers.ts | 36 ++-- helpers/init-helpers.ts | 156 +++++++++--------- helpers/types.ts | 9 +- markets/matic/commons.ts | 2 +- tasks/dev/5_initialize.ts | 4 +- tasks/full/1_address_provider.ts | 8 +- tasks/full/2_lending_pool.ts | 21 ++- tasks/full/3_oracles.ts | 8 +- tasks/full/5-deploy-wethGateWay.ts | 4 +- tasks/full/6-initialize.ts | 9 +- tasks/helpers/deploy-new-asset.ts | 6 +- tasks/misc/initialize-tokens.ts | 6 +- tasks/misc/print-config.ts | 4 +- tasks/verifications/1_general.ts | 20 ++- tasks/verifications/2_tokens.ts | 8 +- test-suites/test-aave/__setup.spec.ts | 1 - .../test-aave/delegation-aware-atoken.spec.ts | 13 +- 19 files changed, 187 insertions(+), 152 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 3db6b821..47c26680 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -3,7 +3,7 @@ import fs from 'fs'; import { HardhatUserConfig } from 'hardhat/types'; // @ts-ignore import { accounts } from './test-wallets.js'; -import { eEthereumNetwork, ePolygonNetwork, eXDaiNetwork } from './helpers/types'; +import { eEthereumNetwork, eNetwork, ePolygonNetwork, eXDaiNetwork } from './helpers/types'; import { BUIDLEREVM_CHAINID, COVERAGE_CHAINID } from './helpers/buidler-constants'; import { NETWORKS_RPC_URL, NETWORKS_DEFAULT_GAS } from './helper-hardhat-config'; @@ -41,7 +41,7 @@ if (!SKIP_LOAD) { require(`${path.join(__dirname, 'tasks/misc')}/set-bre.ts`); -const getCommonNetworkConfig = (networkName: eEthereumNetwork | ePolygonNetwork | eXDaiNetwork, networkId: number) => ({ +const getCommonNetworkConfig = (networkName: eNetwork, networkId: number) => ({ url: NETWORKS_RPC_URL[networkName], hardfork: HARDFORK, blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, diff --git a/helpers/configuration.ts b/helpers/configuration.ts index 894dc11f..39a404c0 100644 --- a/helpers/configuration.ts +++ b/helpers/configuration.ts @@ -4,12 +4,12 @@ import { IReserveParams, PoolConfiguration, ICommonConfiguration, - eEthereumNetwork, + eNetwork, } from './types'; import { getParamPerPool } from './contracts-helpers'; import AaveConfig from '../markets/aave'; import LpConfig from '../markets/lp'; -import MaticConfig from '../markets/matic' +import MaticConfig from '../markets/matic'; import { CommonsConfig } from '../markets/aave/commons'; import { DRE, filterMapBy } from './misc-utils'; import { tEthereumAddress } from './types'; @@ -28,9 +28,9 @@ export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => { case ConfigNames.Aave: return AaveConfig; case ConfigNames.Lp: - return LpConfig; + return LpConfig; case ConfigNames.Matic: - return MaticConfig; + return MaticConfig; case ConfigNames.Commons: return CommonsConfig; default: @@ -51,7 +51,7 @@ export const getReservesConfigByPool = (pool: AavePools): iMultiPoolsAssets => { const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name; - const targetAddress = getParamPerNetwork(config.PoolAdmin, currentNetwork); + const targetAddress = getParamPerNetwork(config.PoolAdmin, currentNetwork); if (targetAddress) { return targetAddress; } @@ -77,7 +77,7 @@ export const getEmergencyAdmin = async ( config: ICommonConfiguration ): Promise => { const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name; - const targetAddress = getParamPerNetwork(config.EmergencyAdmin, currentNetwork); + const targetAddress = getParamPerNetwork(config.EmergencyAdmin, currentNetwork); if (targetAddress) { return targetAddress; } @@ -92,17 +92,17 @@ export const getTreasuryAddress = async ( config: ICommonConfiguration ): Promise => { const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name; - return getParamPerNetwork(config.ReserveFactorTreasuryAddress, currentNetwork); + return getParamPerNetwork(config.ReserveFactorTreasuryAddress, currentNetwork); }; export const getATokenDomainSeparatorPerNetwork = ( - network: eEthereumNetwork, + network: eNetwork, config: ICommonConfiguration ): tEthereumAddress => getParamPerNetwork(config.ATokenDomainSeparator, network); export const getWethAddress = async (config: ICommonConfiguration) => { const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name; - const wethAddress = getParamPerNetwork(config.WETH, currentNetwork); + const wethAddress = getParamPerNetwork(config.WETH, currentNetwork); if (wethAddress) { return wethAddress; } diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 2cd26f57..c9c64aec 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -11,6 +11,13 @@ import { AavePools, iParamsPerNetwork, iParamsPerPool, + ePolygonNetwork, + eXDaiNetwork, + eNetwork, + iParamsPerNetworkAll, + iEthereumParamsPerNetwork, + iPolygonParamsPerNetwork, + iXDaiParamsPerNetwork, } from './types'; import { MintableERC20 } from '../types/MintableERC20'; import { Artifact } from 'hardhat/types'; @@ -132,10 +139,17 @@ export const linkBytecode = (artifact: BuidlerArtifact | Artifact, libraries: an return bytecode; }; -export const getParamPerNetwork = ( - { kovan, ropsten, main, buidlerevm, coverage, tenderlyMain, matic, mumbai }: iParamsPerNetwork, - network: eEthereumNetwork -) => { +export const getParamPerNetwork = (param: iParamsPerNetwork, network: eNetwork) => { + const { + main, + ropsten, + kovan, + coverage, + buidlerevm, + tenderlyMain, + } = param as iEthereumParamsPerNetwork; + const { matic, mumbai } = param as iPolygonParamsPerNetwork; + const { xdai } = param as iXDaiParamsPerNetwork; const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; if (MAINNET_FORK) { return main; @@ -153,13 +167,15 @@ export const getParamPerNetwork = ( case eEthereumNetwork.ropsten: return ropsten; case eEthereumNetwork.main: - return main; - case eEthereumNetwork.matic: - return matic; - case eEthereumNetwork.mumbai: return mumbai; case eEthereumNetwork.tenderlyMain: return tenderlyMain; + case ePolygonNetwork.matic: + return matic; + case ePolygonNetwork.mumbai: + return mumbai; + case eXDaiNetwork.xdai: + return xdai; } }; @@ -167,8 +183,8 @@ export const getParamPerPool = ({ proto, lp }: iParamsPerPool, pool: AaveP switch (pool) { case AavePools.proto: return proto; - case AavePools.lp: - return lp; + case AavePools.lp: + return lp; default: return proto; } diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 308a3087..08cc7b55 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -1,6 +1,7 @@ import { eContractid, eEthereumNetwork, + eNetwork, iMultiPoolsAssets, IReserveParams, tEthereumAddress, @@ -69,21 +70,21 @@ export const initReservesByHelper = async ( let reserveSymbols: string[] = []; let initInputParams: { - aTokenImpl: string, - stableDebtTokenImpl: string, - variableDebtTokenImpl: string, - underlyingAssetDecimals: BigNumberish, - interestRateStrategyAddress: string, - underlyingAsset: string, - treasury: string, - incentivesController: string, - underlyingAssetName: string, - aTokenName: string, - aTokenSymbol: string, - variableDebtTokenName: string, - variableDebtTokenSymbol: string, - stableDebtTokenName: string, - stableDebtTokenSymbol: string, + aTokenImpl: string; + stableDebtTokenImpl: string; + variableDebtTokenImpl: string; + underlyingAssetDecimals: BigNumberish; + interestRateStrategyAddress: string; + underlyingAsset: string; + treasury: string; + incentivesController: string; + underlyingAssetName: string; + aTokenName: string; + aTokenSymbol: string; + variableDebtTokenName: string; + variableDebtTokenSymbol: string; + stableDebtTokenName: string; + stableDebtTokenSymbol: string; }[] = []; let strategyRates: [ @@ -99,10 +100,10 @@ export const initReservesByHelper = async ( let strategyAddresses: Record = {}; let strategyAddressPerAsset: Record = {}; let aTokenType: Record = {}; - let delegationAwareATokenImplementationAddress = ""; - let aTokenImplementationAddress = ""; - let stableDebtTokenImplementationAddress = ""; - let variableDebtTokenImplementationAddress = ""; + let delegationAwareATokenImplementationAddress = ''; + let aTokenImplementationAddress = ''; + let stableDebtTokenImplementationAddress = ''; + let variableDebtTokenImplementationAddress = ''; // NOT WORKING ON MATIC // const tx1 = await waitForTx( @@ -130,21 +131,20 @@ export const initReservesByHelper = async ( if (delegatedAwareReserves.length > 0) { const delegationAwareATokenImplementation = await deployDelegationAwareATokenImpl(verify); delegationAwareATokenImplementationAddress = delegationAwareATokenImplementation.address; - rawInsertContractAddressInDb(`delegationAwareATokenImpl`, delegationAwareATokenImplementationAddress); + rawInsertContractAddressInDb( + `delegationAwareATokenImpl`, + delegationAwareATokenImplementationAddress + ); } const reserves = Object.entries(reservesParams).filter( - ([_, { aTokenImpl }]) => aTokenImpl === eContractid.DelegationAwareAToken || - aTokenImpl === eContractid.AToken + ([_, { aTokenImpl }]) => + aTokenImpl === eContractid.DelegationAwareAToken || aTokenImpl === eContractid.AToken ) as [string, IReserveParams][]; for (let [symbol, params] of reserves) { + const { strategy, aTokenImpl, reserveDecimals } = params; const { - strategy, - aTokenImpl, - reserveDecimals, - } = params; - const { optimalUtilizationRate, baseVariableBorrowRate, variableRateSlope1, @@ -152,7 +152,7 @@ export const initReservesByHelper = async ( stableRateSlope1, stableRateSlope2, } = strategy; - if (!strategyAddresses[strategy.name]) { + if (!strategyAddresses[strategy.name]) { // Strategy does not exist, create a new one rateStrategies[strategy.name] = [ addressProvider.address, @@ -163,21 +163,20 @@ export const initReservesByHelper = async ( stableRateSlope1, stableRateSlope2, ]; - strategyAddresses[strategy.name] = (await deployDefaultReserveInterestRateStrategy( - rateStrategies[strategy.name], - verify - )).address; + strategyAddresses[strategy.name] = ( + await deployDefaultReserveInterestRateStrategy(rateStrategies[strategy.name], verify) + ).address; // This causes the last strategy to be printed twice, once under "DefaultReserveInterestRateStrategy" // and once under the actual `strategyASSET` key. rawInsertContractAddressInDb(strategy.name, strategyAddresses[strategy.name]); } strategyAddressPerAsset[symbol] = strategyAddresses[strategy.name]; - console.log("Strategy address for asset %s: %s", symbol, strategyAddressPerAsset[symbol]) + console.log('Strategy address for asset %s: %s', symbol, strategyAddressPerAsset[symbol]); if (aTokenImpl === eContractid.AToken) { - aTokenType[symbol] = "generic"; + aTokenType[symbol] = 'generic'; } else if (aTokenImpl === eContractid.DelegationAwareAToken) { - aTokenType[symbol] = "delegation aware"; + aTokenType[symbol] = 'delegation aware'; } reserveInitDecimals.push(reserveDecimals); @@ -185,7 +184,7 @@ export const initReservesByHelper = async ( reserveSymbols.push(symbol); } - for (let i = 0; i < reserveSymbols.length; i ++) { + for (let i = 0; i < reserveSymbols.length; i++) { let aTokenToUse: string; if (aTokenType[reserveSymbols[i]] === 'generic') { aTokenToUse = aTokenImplementationAddress; @@ -195,7 +194,7 @@ export const initReservesByHelper = async ( initInputParams.push({ aTokenImpl: aTokenToUse, - stableDebtTokenImpl: stableDebtTokenImplementationAddress, + stableDebtTokenImpl: stableDebtTokenImplementationAddress, variableDebtTokenImpl: variableDebtTokenImplementationAddress, underlyingAssetDecimals: reserveInitDecimals[i], interestRateStrategyAddress: strategyAddressPerAsset[reserveSymbols[i]], @@ -208,7 +207,7 @@ export const initReservesByHelper = async ( variableDebtTokenName: `${variableDebtTokenNamePrefix} ${symbolPrefix}${reserveSymbols[i]}`, variableDebtTokenSymbol: `variableDebt${symbolPrefix}${reserveSymbols[i]}`, stableDebtTokenName: `${stableDebtTokenNamePrefix} ${reserveSymbols[i]}`, - stableDebtTokenSymbol: `stableDebt${symbolPrefix}${reserveSymbols[i]}` + stableDebtTokenSymbol: `stableDebt${symbolPrefix}${reserveSymbols[i]}`, }); } @@ -230,7 +229,7 @@ export const initReservesByHelper = async ( //gasUsage = gasUsage.add(tx3.gasUsed); } - return gasUsage; // Deprecated + return gasUsage; // Deprecated }; export const getPairsTokenAggregator = ( @@ -276,7 +275,7 @@ export const configureReservesByHelper = async ( const reserveFactors: string[] = []; const stableRatesEnabled: boolean[] = []; - const inputParams : { + const inputParams: { asset: string; baseLTV: BigNumberish; liquidationThreshold: BigNumberish; @@ -319,7 +318,7 @@ export const configureReservesByHelper = async ( liquidationThreshold: liquidationThreshold, liquidationBonus: liquidationBonus, reserveFactor: reserveFactor, - stableBorrowingEnabled: stableBorrowRateEnabled + stableBorrowingEnabled: stableBorrowRateEnabled, }); tokens.push(tokenAddress); @@ -342,10 +341,9 @@ export const configureReservesByHelper = async ( console.log(`- Configure reserves in ${chunkedInputParams.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedInputParams.length; chunkIndex++) { await waitForTx( - await atokenAndRatesDeployer.configureReserves( - chunkedInputParams[chunkIndex], - { gasLimit: 12000000 } - ) + await atokenAndRatesDeployer.configureReserves(chunkedInputParams[chunkIndex], { + gasLimit: 12000000, + }) ); console.log(` - Init for: ${chunkedSymbols[chunkIndex].join(', ')}`); } @@ -356,7 +354,7 @@ export const configureReservesByHelper = async ( const getAddressById = async ( id: string, - network: eEthereumNetwork + network: eNetwork ): Promise => (await getDb().get(`${id}.${network}`).value())?.address || undefined; @@ -403,27 +401,25 @@ export const initTokenReservesByHelper = async ( let reserveSymbols: string[] = []; let initInputParams: { - aTokenImpl: string, - stableDebtTokenImpl: string, - variableDebtTokenImpl: string, - underlyingAssetDecimals: BigNumberish, - interestRateStrategyAddress: string, - underlyingAsset: string, - treasury: string, - incentivesController: string, - underlyingAssetName: string, - aTokenName: string, - aTokenSymbol: string, - variableDebtTokenName: string, - variableDebtTokenSymbol: string, - stableDebtTokenName: string, - stableDebtTokenSymbol: string, + aTokenImpl: string; + stableDebtTokenImpl: string; + variableDebtTokenImpl: string; + underlyingAssetDecimals: BigNumberish; + interestRateStrategyAddress: string; + underlyingAsset: string; + treasury: string; + incentivesController: string; + underlyingAssetName: string; + aTokenName: string; + aTokenSymbol: string; + variableDebtTokenName: string; + variableDebtTokenSymbol: string; + stableDebtTokenName: string; + stableDebtTokenSymbol: string; }[] = []; const network = - process.env.MAINNET_FORK === 'true' - ? eEthereumNetwork.main - : (DRE.network.name as eEthereumNetwork); + process.env.MAINNET_FORK === 'true' ? eEthereumNetwork.main : (DRE.network.name as eNetwork); // Grab config from DB for (const [symbol, address] of Object.entries(tokenAddresses)) { const { aTokenAddress } = await protocolDataProvider.getReserveTokensAddresses(address); @@ -439,10 +435,11 @@ export const initTokenReservesByHelper = async ( } let stableTokenImpl = await getAddressById(`stableDebtTokenImpl`, network); let variableTokenImpl = await getAddressById(`variableDebtTokenImpl`, network); - let aTokenImplementation: string | undefined = ""; - const [, { aTokenImpl, strategy }] = (Object.entries(reservesParams) as [string, IReserveParams][])[ - reserveParamIndex - ]; + let aTokenImplementation: string | undefined = ''; + const [, { aTokenImpl, strategy }] = (Object.entries(reservesParams) as [ + string, + IReserveParams + ][])[reserveParamIndex]; if (aTokenImpl === eContractid.AToken) { aTokenImplementation = await getAddressById(`aTokenImpl`, network); } else if (aTokenImpl === eContractid.DelegationAwareAToken) { @@ -458,7 +455,7 @@ export const initTokenReservesByHelper = async ( tokenAddresses[symbol], ZERO_ADDRESS, // Incentives controller `Aave stable debt bearing ${symbol}`, - `stableDebt${symbol}` + `stableDebt${symbol}`, ], verify ); @@ -471,7 +468,7 @@ export const initTokenReservesByHelper = async ( tokenAddresses[symbol], ZERO_ADDRESS, // Incentives Controller `Aave variable debt bearing ${symbol}`, - `variableDebt${symbol}` + `variableDebt${symbol}`, ], verify ); @@ -489,19 +486,16 @@ export const initTokenReservesByHelper = async ( treasuryAddress, ZERO_ADDRESS, `Aave interest bearing ${symbol}`, - `a${symbol}` + `a${symbol}`, ], verify ); aTokenImplementation = aToken.address; } if (!strategyImpl) { - const [ - , - { - strategy - }, - ] = (Object.entries(reservesParams) as [string, IReserveParams][])[reserveParamIndex]; + const [, { strategy }] = (Object.entries(reservesParams) as [string, IReserveParams][])[ + reserveParamIndex + ]; const { optimalUtilizationRate, baseVariableBorrowRate, @@ -543,10 +537,10 @@ export const initTokenReservesByHelper = async ( reserveSymbols.push(symbol); } - for (let i = 0; i < deployedATokens.length; i ++) { + for (let i = 0; i < deployedATokens.length; i++) { initInputParams.push({ aTokenImpl: deployedATokens[i], - stableDebtTokenImpl: deployedStableTokens[i], + stableDebtTokenImpl: deployedStableTokens[i], variableDebtTokenImpl: deployedVariableTokens[i], underlyingAssetDecimals: reserveInitDecimals[i], interestRateStrategyAddress: deployedRates[i], @@ -559,7 +553,7 @@ export const initTokenReservesByHelper = async ( variableDebtTokenName: `Aave variable debt bearing ${reserveSymbols[i]}`, variableDebtTokenSymbol: `variableDebt${reserveSymbols[i]}`, stableDebtTokenName: `Aave stable debt bearing ${reserveSymbols[i]}`, - stableDebtTokenSymbol: `stableDebt${reserveSymbols[i]}` + stableDebtTokenSymbol: `stableDebt${reserveSymbols[i]}`, }); } @@ -582,7 +576,7 @@ export const initTokenReservesByHelper = async ( // Set deployer back as admin await waitForTx(await addressProvider.setPoolAdmin(admin)); - return gasUsage; // No longer relevant + return gasUsage; // No longer relevant }; // Function deprecated diff --git a/helpers/types.ts b/helpers/types.ts index 526b2f98..39237440 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -4,6 +4,8 @@ export interface SymbolMap { [symbol: string]: T; } +export type eNetwork = eEthereumNetwork | ePolygonNetwork | eXDaiNetwork; + export enum eEthereumNetwork { buidlerevm = 'buidlerevm', kovan = 'kovan', @@ -16,7 +18,7 @@ export enum eEthereumNetwork { export enum ePolygonNetwork { matic = 'matic', - mumbai = 'mumbail', + mumbai = 'mumbai', } export enum eXDaiNetwork { @@ -398,6 +400,11 @@ export type iParamsPerNetwork = | iPolygonParamsPerNetwork | iXDaiParamsPerNetwork; +export interface iParamsPerNetworkAll + extends iEthereumParamsPerNetwork, + iPolygonParamsPerNetwork, + iXDaiParamsPerNetwork {} + export interface iEthereumParamsPerNetwork { [eEthereumNetwork.coverage]: T; [eEthereumNetwork.buidlerevm]: T; diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index 784f156d..109bda77 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -97,7 +97,7 @@ export const CommonsConfig: ICommonConfiguration = { }, WethGateway: { [ePolygonNetwork.mumbai]: '', - [ePolygonNetwork.matic]: '', + [ePolygonNetwork.matic]: '0x4fAfE6704a78e21Fc43C01bEb153607604F6768a', }, AaveOracle: { [ePolygonNetwork.mumbai]: '', diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index 6c11ad6d..a1ad9970 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -8,7 +8,7 @@ import { authorizeWETHGateway, } from '../../helpers/contracts-deployments'; import { getParamPerNetwork } from '../../helpers/contracts-helpers'; -import { eEthereumNetwork } from '../../helpers/types'; +import { eNetwork } from '../../helpers/types'; import { ConfigNames, getReservesConfigByPool, @@ -33,7 +33,7 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ verify, pool }, localBRE) => { await localBRE.run('set-DRE'); - const network = localBRE.network.name; + const network = localBRE.network.name; const poolConfig = loadPoolConfig(pool); const { ATokenNamePrefix, diff --git a/tasks/full/1_address_provider.ts b/tasks/full/1_address_provider.ts index 87e3e23d..88852c0c 100644 --- a/tasks/full/1_address_provider.ts +++ b/tasks/full/1_address_provider.ts @@ -11,7 +11,7 @@ import { getGenesisPoolAdmin, getEmergencyAdmin, } from '../../helpers/configuration'; -import { eEthereumNetwork } from '../../helpers/types'; +import { eNetwork } from '../../helpers/types'; import { getFirstSigner, getLendingPoolAddressesProviderRegistry, @@ -31,7 +31,7 @@ task( .setAction(async ({ verify, pool }, DRE) => { await DRE.run('set-DRE'); let signer: Signer; - const network = DRE.network.name; + const network = DRE.network.name; const poolConfig = loadPoolConfig(pool); const { ProviderId, MarketId } = poolConfig; @@ -81,7 +81,7 @@ task( // 2. Deploy address provider and set genesis manager const addressesProvider = await deployLendingPoolAddressesProvider(MarketId, verify); - + // DISABLE SEC. 3 FOR GOVERNANCE USE! // 3. Set the provider at the Registry await waitForTx( @@ -92,7 +92,7 @@ task( ); // 4. Set pool admins - + await waitForTx(await addressesProvider.setPoolAdmin(await getGenesisPoolAdmin(poolConfig))); await waitForTx(await addressesProvider.setEmergencyAdmin(await getEmergencyAdmin(poolConfig))); diff --git a/tasks/full/2_lending_pool.ts b/tasks/full/2_lending_pool.ts index fd6e1352..5f92b8eb 100644 --- a/tasks/full/2_lending_pool.ts +++ b/tasks/full/2_lending_pool.ts @@ -6,7 +6,7 @@ import { deployLendingPoolConfigurator, deployStableAndVariableTokensHelper, } from '../../helpers/contracts-deployments'; -import { eContractid, eEthereumNetwork } from '../../helpers/types'; +import { eContractid, eNetwork } from '../../helpers/types'; import { notFalsyOrZeroAddress, waitForTx } from '../../helpers/misc-utils'; import { getLendingPoolAddressesProvider, @@ -22,20 +22,20 @@ task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment') .setAction(async ({ verify, pool }, DRE: HardhatRuntimeEnvironment) => { try { await DRE.run('set-DRE'); - const network = DRE.network.name; - const poolConfig = loadPoolConfig(pool) + const network = DRE.network.name; + const poolConfig = loadPoolConfig(pool); const addressesProvider = await getLendingPoolAddressesProvider(); - + const { LendingPool, LendingPoolConfigurator } = poolConfig; // Reuse/deploy lending pool implementation - let lendingPoolImplAddress = getParamPerNetwork(LendingPool, network) + let lendingPoolImplAddress = getParamPerNetwork(LendingPool, network); if (!notFalsyOrZeroAddress(lendingPoolImplAddress)) { - console.log("\tDeploying new lending pool implementation & libraries..."); + console.log('\tDeploying new lending pool implementation & libraries...'); const lendingPoolImpl = await deployLendingPool(verify); lendingPoolImplAddress = lendingPoolImpl.address; } - console.log("\tSetting lending pool implementation with address:" , lendingPoolImplAddress); + console.log('\tSetting lending pool implementation with address:', lendingPoolImplAddress); // Set lending pool impl to Address provider await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImplAddress)); @@ -47,11 +47,14 @@ task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment') // Reuse/deploy lending pool configurator let lendingPoolConfiguratorImplAddress = getParamPerNetwork(LendingPoolConfigurator, network); //await deployLendingPoolConfigurator(verify); if (!notFalsyOrZeroAddress(lendingPoolConfiguratorImplAddress)) { - console.log("\tDeploying new configurator implementation..."); + console.log('\tDeploying new configurator implementation...'); const lendingPoolConfiguratorImpl = await deployLendingPoolConfigurator(verify); lendingPoolConfiguratorImplAddress = lendingPoolConfiguratorImpl.address; } - console.log("\tSetting lending pool configurator implementation with address:" , lendingPoolConfiguratorImplAddress); + console.log( + '\tSetting lending pool configurator implementation with address:', + lendingPoolConfiguratorImplAddress + ); // Set lending pool conf impl to Address Provider await waitForTx( await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImplAddress) diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index 67a8fbd7..e479b6b1 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -2,7 +2,7 @@ import { task } from 'hardhat/config'; import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { deployAaveOracle, deployLendingRateOracle } from '../../helpers/contracts-deployments'; import { setInitialMarketRatesInRatesOracleByHelper } from '../../helpers/oracles-helpers'; -import { ICommonConfiguration, eEthereumNetwork, SymbolMap } from '../../helpers/types'; +import { ICommonConfiguration, eNetwork, SymbolMap } from '../../helpers/types'; import { waitForTx, notFalsyOrZeroAddress } from '../../helpers/misc-utils'; import { ConfigNames, @@ -25,7 +25,7 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') .setAction(async ({ verify, pool }, DRE) => { try { await DRE.run('set-DRE'); - const network = DRE.network.name; + const network = DRE.network.name; const poolConfig = loadPoolConfig(pool); const { ProtocolGlobalParams: { UsdAddress }, @@ -56,7 +56,7 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') aaveOracle = await deployAaveOracle( [tokens, aggregators, fallbackOracleAddress, await getWethAddress(poolConfig)], verify - ); + ); } const lendingRateOracle = notFalsyOrZeroAddress(lendingRateOracleAddress) @@ -73,7 +73,7 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') admin ); //} - console.log("ORACLES: %s and %s", aaveOracle.address, lendingRateOracle.address); + console.log('ORACLES: %s and %s', aaveOracle.address, lendingRateOracle.address); // Register the proxy price provider on the addressesProvider await waitForTx(await addressesProvider.setPriceOracle(aaveOracle.address)); await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); diff --git a/tasks/full/5-deploy-wethGateWay.ts b/tasks/full/5-deploy-wethGateWay.ts index 12c97a15..2774f107 100644 --- a/tasks/full/5-deploy-wethGateWay.ts +++ b/tasks/full/5-deploy-wethGateWay.ts @@ -4,7 +4,7 @@ import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { loadPoolConfig, ConfigNames, getWethAddress } from '../../helpers/configuration'; import { deployWETHGateway } from '../../helpers/contracts-deployments'; import { DRE } from '../../helpers/misc-utils'; -import { eEthereumNetwork } from '../../helpers/types'; +import { eNetwork } from '../../helpers/types'; const CONTRACT_NAME = 'WETHGateway'; @@ -13,7 +13,7 @@ task(`full-deploy-weth-gateway`, `Deploys the ${CONTRACT_NAME} contract`) .addFlag('verify', `Verify ${CONTRACT_NAME} contract via Etherscan API.`) .setAction(async ({ verify, pool }, localBRE) => { await localBRE.run('set-DRE'); - const network = localBRE.network.name; + const network = localBRE.network.name; const poolConfig = loadPoolConfig(pool); const Weth = await getWethAddress(poolConfig); const { WethGateway } = poolConfig; diff --git a/tasks/full/6-initialize.ts b/tasks/full/6-initialize.ts index b5ee3aea..f4384e09 100644 --- a/tasks/full/6-initialize.ts +++ b/tasks/full/6-initialize.ts @@ -13,7 +13,7 @@ import { getTreasuryAddress, } from '../../helpers/configuration'; import { getWETHGateway } from '../../helpers/contracts-getters'; -import { eEthereumNetwork, ICommonConfiguration } from '../../helpers/types'; +import { eNetwork, ICommonConfiguration } from '../../helpers/types'; import { notFalsyOrZeroAddress, waitForTx } from '../../helpers/misc-utils'; import { initReservesByHelper, configureReservesByHelper } from '../../helpers/init-helpers'; import { exit } from 'process'; @@ -29,7 +29,7 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') .setAction(async ({ verify, pool }, localBRE) => { try { await localBRE.run('set-DRE'); - const network = localBRE.network.name; + const network = localBRE.network.name; const poolConfig = loadPoolConfig(pool); const { ATokenNamePrefix, @@ -79,7 +79,10 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') } // Seems unnecessary to register the collateral manager in the JSON db - console.log("\tSetting lending pool collateral manager implementation with address", collateralManagerAddress); + console.log( + '\tSetting lending pool collateral manager implementation with address', + collateralManagerAddress + ); await waitForTx( await addressesProvider.setLendingPoolCollateralManager(collateralManagerAddress) ); diff --git a/tasks/helpers/deploy-new-asset.ts b/tasks/helpers/deploy-new-asset.ts index 50cde45b..03d102c4 100644 --- a/tasks/helpers/deploy-new-asset.ts +++ b/tasks/helpers/deploy-new-asset.ts @@ -1,5 +1,5 @@ import { task } from 'hardhat/config'; -import { EthereumNetwork } from '../../helpers/types'; +import { eEthereumNetwork } from '../../helpers/types'; import { getTreasuryAddress } from '../../helpers/configuration'; import * as marketConfigs from '../../markets/aave'; import * as reserveConfigs from '../../markets/aave/reservesConfigs'; @@ -18,7 +18,7 @@ const LENDING_POOL_ADDRESS_PROVIDER = { kovan: '0x652B2937Efd0B5beA1c8d54293FC1289672AFC6b', }; -const isSymbolValid = (symbol: string, network: EthereumNetwork) => +const isSymbolValid = (symbol: string, network: eEthereumNetwork) => Object.keys(reserveConfigs).includes('strategy' + symbol) && marketConfigs.AaveConfig.ReserveAssets[network][symbol] && marketConfigs.AaveConfig.ReservesConfig[symbol] === reserveConfigs['strategy' + symbol]; @@ -28,7 +28,7 @@ task('external:deploy-new-asset', 'Deploy A token, Debt Tokens, Risk Parameters' .addFlag('verify', 'Verify contracts at Etherscan') .setAction(async ({ verify, symbol }, localBRE) => { const network = localBRE.network.name; - if (!isSymbolValid(symbol, network as EthereumNetwork)) { + if (!isSymbolValid(symbol, network as eEthereumNetwork)) { throw new Error( ` WRONG RESERVE ASSET SETUP: diff --git a/tasks/misc/initialize-tokens.ts b/tasks/misc/initialize-tokens.ts index 91822f84..680e1337 100644 --- a/tasks/misc/initialize-tokens.ts +++ b/tasks/misc/initialize-tokens.ts @@ -1,7 +1,7 @@ import { task } from 'hardhat/config'; import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { loadPoolConfig, ConfigNames, getTreasuryAddress } from '../../helpers/configuration'; -import { eEthereumNetwork, ICommonConfiguration } from '../../helpers/types'; +import { eEthereumNetwork, eNetwork, ICommonConfiguration } from '../../helpers/types'; import { waitForTx } from '../../helpers/misc-utils'; import { initTokenReservesByHelper } from '../../helpers/init-helpers'; import { exit } from 'process'; @@ -23,9 +23,7 @@ task('full:initialize-tokens', 'Initialize lending pool configuration.') await DRE.run('set-DRE'); let signer: Signer; const network = - process.env.MAINNET_FORK === 'true' - ? eEthereumNetwork.main - : DRE.network.name; + process.env.MAINNET_FORK === 'true' ? eEthereumNetwork.main : DRE.network.name; const poolConfig = loadPoolConfig(pool); const { ReserveAssets, ReservesConfig } = poolConfig as ICommonConfiguration; diff --git a/tasks/misc/print-config.ts b/tasks/misc/print-config.ts index 6a7db42a..722d308c 100644 --- a/tasks/misc/print-config.ts +++ b/tasks/misc/print-config.ts @@ -7,7 +7,7 @@ import { } from '../../helpers/contracts-getters'; import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { DRE } from '../../helpers/misc-utils'; -import { eEthereumNetwork } from '../../helpers/types'; +import { eEthereumNetwork, eNetwork, ePolygonNetwork, eXDaiNetwork } from '../../helpers/types'; task('print-config', 'Inits the DRE, to have access to all the plugins') .addParam('dataProvider', 'Address of AaveProtocolDataProvider') @@ -17,7 +17,7 @@ task('print-config', 'Inits the DRE, to have access to all the plugins') const network = process.env.MAINNET_FORK === 'true' ? eEthereumNetwork.main - : (localBRE.network.name as eEthereumNetwork); + : (localBRE.network.name as eNetwork); const poolConfig = loadPoolConfig(pool); const providerRegistryAddress = getParamPerNetwork(poolConfig.ProviderRegistry, network); diff --git a/tasks/verifications/1_general.ts b/tasks/verifications/1_general.ts index 80a76162..fef0e510 100644 --- a/tasks/verifications/1_general.ts +++ b/tasks/verifications/1_general.ts @@ -25,14 +25,14 @@ import { import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { verifyContract } from '../../helpers/etherscan-verification'; import { notFalsyOrZeroAddress } from '../../helpers/misc-utils'; -import { eEthereumNetwork, ICommonConfiguration } from '../../helpers/types'; +import { eNetwork, ICommonConfiguration } from '../../helpers/types'; task('verify:general', 'Verify contracts at Etherscan') .addFlag('all', 'Verify all contracts at Etherscan') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ all, pool }, localDRE) => { await localDRE.run('set-DRE'); - const network = localDRE.network.name as eEthereumNetwork; + const network = localDRE.network.name as eNetwork; const poolConfig = loadPoolConfig(pool); const { ReserveAssets, @@ -52,7 +52,7 @@ task('verify:general', 'Verify contracts at Etherscan') ? await getLendingPoolAddressesProviderRegistry(registryAddress) : await getLendingPoolAddressesProviderRegistry(); const lendingPoolAddress = await addressesProvider.getLendingPool(); - const lendingPoolConfiguratorAddress = await addressesProvider.getLendingPoolConfigurator();//getLendingPoolConfiguratorProxy(); + const lendingPoolConfiguratorAddress = await addressesProvider.getLendingPoolConfigurator(); //getLendingPoolConfiguratorProxy(); const lendingPoolCollateralManagerAddress = await addressesProvider.getLendingPoolCollateralManager(); if (all) { @@ -61,13 +61,21 @@ task('verify:general', 'Verify contracts at Etherscan') ? await getLendingPoolImpl(lendingPoolImplAddress) : await getLendingPoolImpl(); - const lendingPoolConfiguratorImplAddress = getParamPerNetwork(LendingPoolConfigurator, network); + const lendingPoolConfiguratorImplAddress = getParamPerNetwork( + LendingPoolConfigurator, + network + ); const lendingPoolConfiguratorImpl = notFalsyOrZeroAddress(lendingPoolConfiguratorImplAddress) ? await getLendingPoolConfiguratorImpl(lendingPoolConfiguratorImplAddress) : await getLendingPoolConfiguratorImpl(); - const lendingPoolCollateralManagerImplAddress = getParamPerNetwork(LendingPoolCollateralManager, network); - const lendingPoolCollateralManagerImpl = notFalsyOrZeroAddress(lendingPoolCollateralManagerImplAddress) + const lendingPoolCollateralManagerImplAddress = getParamPerNetwork( + LendingPoolCollateralManager, + network + ); + const lendingPoolCollateralManagerImpl = notFalsyOrZeroAddress( + lendingPoolCollateralManagerImplAddress + ) ? await getLendingPoolCollateralManagerImpl(lendingPoolCollateralManagerImplAddress) : await getLendingPoolCollateralManagerImpl(); diff --git a/tasks/verifications/2_tokens.ts b/tasks/verifications/2_tokens.ts index a611c275..52d77ffd 100644 --- a/tasks/verifications/2_tokens.ts +++ b/tasks/verifications/2_tokens.ts @@ -15,24 +15,24 @@ import { } from '../../helpers/contracts-getters'; import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { verifyContract } from '../../helpers/etherscan-verification'; -import { eEthereumNetwork, ICommonConfiguration, IReserveParams } from '../../helpers/types'; +import { eNetwork, ICommonConfiguration, IReserveParams } from '../../helpers/types'; import { LendingPoolConfiguratorFactory, LendingPoolFactory } from '../../types'; task('verify:tokens', 'Deploy oracles for dev enviroment') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ verify, all, pool }, localDRE) => { await localDRE.run('set-DRE'); - const network = localDRE.network.name as eEthereumNetwork; + const network = localDRE.network.name as eNetwork; const poolConfig = loadPoolConfig(pool); const { ReserveAssets, ReservesConfig } = poolConfig as ICommonConfiguration; const treasuryAddress = await getTreasuryAddress(poolConfig); const addressesProvider = await getLendingPoolAddressesProvider(); const lendingPoolProxy = LendingPoolFactory.connect( - await addressesProvider.getLendingPool(), + await addressesProvider.getLendingPool(), await getFirstSigner() ); - + const lendingPoolConfigurator = LendingPoolConfiguratorFactory.connect( await addressesProvider.getLendingPoolConfigurator(), await getFirstSigner() diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index c9a54f7f..79be455b 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -28,7 +28,6 @@ import { deployFlashLiquidationAdapter, authorizeWETHGateway, } from '../../helpers/contracts-deployments'; -import { eEthereumNetwork } from '../../helpers/types'; import { Signer } from 'ethers'; import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types'; import { MintableERC20 } from '../../types/MintableERC20'; diff --git a/test-suites/test-aave/delegation-aware-atoken.spec.ts b/test-suites/test-aave/delegation-aware-atoken.spec.ts index 656f7422..7e938172 100644 --- a/test-suites/test-aave/delegation-aware-atoken.spec.ts +++ b/test-suites/test-aave/delegation-aware-atoken.spec.ts @@ -3,7 +3,7 @@ import { BUIDLEREVM_CHAINID } from '../../helpers/buidler-constants'; import { buildPermitParams, getSignatureFromTypedData } from '../../helpers/contracts-helpers'; import { expect } from 'chai'; import { ethers } from 'ethers'; -import { eEthereumNetwork, ProtocolErrors } from '../../helpers/types'; +import { ProtocolErrors } from '../../helpers/types'; import { makeSuite, TestEnv } from './helpers/make-suite'; import { DRE } from '../../helpers/misc-utils'; import { @@ -35,10 +35,17 @@ makeSuite('AToken: underlying delegation', (testEnv: TestEnv) => { delegationERC20 = await deployMintableDelegationERC20(['DEL', 'DEL', '18']); delegationAToken = await deployDelegationAwareAToken( - [pool.address, delegationERC20.address, await getTreasuryAddress(AaveConfig), ZERO_ADDRESS, 'aDEL', 'aDEL'], + [ + pool.address, + delegationERC20.address, + await getTreasuryAddress(AaveConfig), + ZERO_ADDRESS, + 'aDEL', + 'aDEL', + ], false ); - + //await delegationAToken.initialize(pool.address, ZERO_ADDRESS, delegationERC20.address, ZERO_ADDRESS, '18', 'aDEL', 'aDEL'); console.log((await delegationAToken.decimals()).toString()); From d41edec1ab6b248653f6b12d78c15e38a74fafa2 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Tue, 23 Feb 2021 10:59:02 -0500 Subject: [PATCH 153/219] Merged feat/lp-market-updated-deployment --- helpers/configuration.ts | 12 ++++---- helpers/contracts-getters.ts | 2 +- helpers/contracts-helpers.ts | 6 ++-- helpers/init-helpers.ts | 10 +++---- helpers/types.ts | 16 ++-------- markets/{lp => amm}/commons.ts | 0 markets/{lp => amm}/index.ts | 8 ++--- markets/{lp => amm}/rateStrategies.ts | 4 +-- markets/{lp => amm}/reservesConfigs.ts | 30 +++++++++---------- package-lock.json | 8 ++--- package.json | 10 +++---- tasks/full/2_lending_pool.ts | 2 +- .../{lp.mainnet.ts => amm.mainnet.ts} | 4 +-- test-suites/test-aave/__setup.spec.ts | 1 + .../{test-lp => test-amm}/__setup.spec.ts | 24 +++++++-------- .../addresses-provider-registry.spec.ts | 0 .../atoken-modifiers.spec.ts | 0 .../atoken-permit.spec.ts | 0 .../atoken-transfer.spec.ts | 2 +- .../configurator.spec.ts | 2 +- .../delegation-aware-atoken.spec.ts | 4 +-- .../{test-lp => test-amm}/flashloan.spec.ts | 0 .../{test-lp => test-amm}/helpers/actions.ts | 0 .../helpers/almost-equal.ts | 0 .../helpers/make-suite.ts | 4 +-- .../helpers/scenario-engine.ts | 0 .../helpers/scenarios/borrow-negatives.json | 0 .../scenarios/borrow-repay-stable.json | 0 .../scenarios/borrow-repay-variable.json | 0 .../helpers/scenarios/credit-delegation.json | 0 .../helpers/scenarios/deposit.json | 0 .../scenarios/rebalance-stable-rate.json | 0 .../scenarios/set-use-as-collateral.json | 0 .../helpers/scenarios/swap-rate-mode.json | 0 .../helpers/scenarios/withdraw-negatives.json | 0 .../helpers/scenarios/withdraw.json | 0 .../helpers/utils/calculations.ts | 0 .../helpers/utils/helpers.ts | 0 .../helpers/utils/interfaces/index.ts | 0 .../helpers/utils/math.ts | 0 .../lending-pool-addresses-provider.spec.ts | 0 .../liquidation-atoken.spec.ts | 0 .../liquidation-underlying.spec.ts | 2 +- .../mainnet/check-list.spec.ts | 0 .../pausable-functions.spec.ts | 0 .../pool-modifiers.spec.ts | 0 .../rate-strategy.spec.ts | 0 .../{test-lp => test-amm}/scenario.spec.ts | 4 +-- .../stable-rate-economy.spec.ts | 0 .../stable-token.spec.ts | 0 .../subgraph-scenarios.spec.ts | 2 +- .../uniswapAdapters.base.spec.ts | 0 .../uniswapAdapters.flashLiquidation.spec.ts | 0 .../uniswapAdapters.liquiditySwap.spec.ts | 0 .../uniswapAdapters.repay.spec.ts | 0 .../upgradeability.spec.ts | 0 .../variable-debt-token.spec.ts | 0 .../weth-gateway.spec.ts | 0 58 files changed, 74 insertions(+), 83 deletions(-) rename markets/{lp => amm}/commons.ts (100%) rename markets/{lp => amm}/index.ts (96%) rename markets/{lp => amm}/rateStrategies.ts (94%) rename markets/{lp => amm}/reservesConfigs.ts (92%) rename tasks/migrations/{lp.mainnet.ts => amm.mainnet.ts} (95%) rename test-suites/{test-lp => test-amm}/__setup.spec.ts (93%) rename test-suites/{test-lp => test-amm}/addresses-provider-registry.spec.ts (100%) rename test-suites/{test-lp => test-amm}/atoken-modifiers.spec.ts (100%) rename test-suites/{test-lp => test-amm}/atoken-permit.spec.ts (100%) rename test-suites/{test-lp => test-amm}/atoken-transfer.spec.ts (98%) rename test-suites/{test-lp => test-amm}/configurator.spec.ts (99%) rename test-suites/{test-lp => test-amm}/delegation-aware-atoken.spec.ts (96%) rename test-suites/{test-lp => test-amm}/flashloan.spec.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/actions.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/almost-equal.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/make-suite.ts (98%) rename test-suites/{test-lp => test-amm}/helpers/scenario-engine.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/borrow-negatives.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/borrow-repay-stable.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/borrow-repay-variable.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/credit-delegation.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/deposit.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/rebalance-stable-rate.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/set-use-as-collateral.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/swap-rate-mode.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/withdraw-negatives.json (100%) rename test-suites/{test-lp => test-amm}/helpers/scenarios/withdraw.json (100%) rename test-suites/{test-lp => test-amm}/helpers/utils/calculations.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/utils/helpers.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/utils/interfaces/index.ts (100%) rename test-suites/{test-lp => test-amm}/helpers/utils/math.ts (100%) rename test-suites/{test-lp => test-amm}/lending-pool-addresses-provider.spec.ts (100%) rename test-suites/{test-lp => test-amm}/liquidation-atoken.spec.ts (100%) rename test-suites/{test-lp => test-amm}/liquidation-underlying.spec.ts (99%) rename test-suites/{test-lp => test-amm}/mainnet/check-list.spec.ts (100%) rename test-suites/{test-lp => test-amm}/pausable-functions.spec.ts (100%) rename test-suites/{test-lp => test-amm}/pool-modifiers.spec.ts (100%) rename test-suites/{test-lp => test-amm}/rate-strategy.spec.ts (100%) rename test-suites/{test-lp => test-amm}/scenario.spec.ts (93%) rename test-suites/{test-lp => test-amm}/stable-rate-economy.spec.ts (100%) rename test-suites/{test-lp => test-amm}/stable-token.spec.ts (100%) rename test-suites/{test-lp => test-amm}/subgraph-scenarios.spec.ts (96%) rename test-suites/{test-lp => test-amm}/uniswapAdapters.base.spec.ts (100%) rename test-suites/{test-lp => test-amm}/uniswapAdapters.flashLiquidation.spec.ts (100%) rename test-suites/{test-lp => test-amm}/uniswapAdapters.liquiditySwap.spec.ts (100%) rename test-suites/{test-lp => test-amm}/uniswapAdapters.repay.spec.ts (100%) rename test-suites/{test-lp => test-amm}/upgradeability.spec.ts (100%) rename test-suites/{test-lp => test-amm}/variable-debt-token.spec.ts (100%) rename test-suites/{test-lp => test-amm}/weth-gateway.spec.ts (100%) diff --git a/helpers/configuration.ts b/helpers/configuration.ts index 39a404c0..618eec82 100644 --- a/helpers/configuration.ts +++ b/helpers/configuration.ts @@ -8,8 +8,8 @@ import { } from './types'; import { getParamPerPool } from './contracts-helpers'; import AaveConfig from '../markets/aave'; -import LpConfig from '../markets/lp'; import MaticConfig from '../markets/matic'; +import AmmConfig from '../markets/amm'; import { CommonsConfig } from '../markets/aave/commons'; import { DRE, filterMapBy } from './misc-utils'; import { tEthereumAddress } from './types'; @@ -19,18 +19,18 @@ import { deployWETHMocked } from './contracts-deployments'; export enum ConfigNames { Commons = 'Commons', Aave = 'Aave', - Lp = 'Lp', Matic = 'Matic', + Amm = 'Amm', } export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => { switch (configName) { case ConfigNames.Aave: return AaveConfig; - case ConfigNames.Lp: - return LpConfig; case ConfigNames.Matic: return MaticConfig; + case ConfigNames.Amm: + return AmmConfig; case ConfigNames.Commons: return CommonsConfig; default: @@ -48,8 +48,8 @@ export const getReservesConfigByPool = (pool: AavePools): iMultiPoolsAssets { - const { ETH, USD, WETH, LpWETH, ...assetsAddressesWithoutEth } = allAssetsAddresses; + const { ETH, USD, WETH, ...assetsAddressesWithoutEth } = allAssetsAddresses; const pairs = Object.entries(assetsAddressesWithoutEth).map(([tokenSymbol, tokenAddress]) => { //if (true/*tokenSymbol !== 'WETH' && tokenSymbol !== 'ETH' && tokenSymbol !== 'LpWETH'*/) { diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index c9c64aec..d025b694 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -179,12 +179,12 @@ export const getParamPerNetwork = (param: iParamsPerNetwork, network: eNet } }; -export const getParamPerPool = ({ proto, lp }: iParamsPerPool, pool: AavePools) => { +export const getParamPerPool = ({ proto, amm }: iParamsPerPool, pool: AavePools) => { switch (pool) { case AavePools.proto: return proto; - case AavePools.lp: - return lp; + case AavePools.amm: + return amm; default: return proto; } diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 08cc7b55..f0014347 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -216,7 +216,7 @@ export const initReservesByHelper = async ( const chunkedInitInputParams = chunk(initInputParams, initChunks); const configurator = await getLendingPoolConfiguratorProxy(); - await waitForTx(await addressProvider.setPoolAdmin(admin)); + //await waitForTx(await addressProvider.setPoolAdmin(admin)); console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) { @@ -386,7 +386,7 @@ export const initTokenReservesByHelper = async ( const poolAddress = await addressProvider.getLendingPool(); // Set aTokenAndRatesDeployer as temporal admin - await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address)); + //await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address)); // CHUNK CONFIGURATION const initChunks = 4; @@ -562,7 +562,7 @@ export const initTokenReservesByHelper = async ( const chunkedInitInputParams = chunk(initInputParams, initChunks); const configurator = await getLendingPoolConfiguratorProxy(); - await waitForTx(await addressProvider.setPoolAdmin(admin)); + //await waitForTx(await addressProvider.setPoolAdmin(admin)); console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) { @@ -575,8 +575,8 @@ export const initTokenReservesByHelper = async ( } // Set deployer back as admin - await waitForTx(await addressProvider.setPoolAdmin(admin)); - return gasUsage; // No longer relevant + //await waitForTx(await addressProvider.setPoolAdmin(admin)); + return gasUsage; // No longer relevant }; // Function deprecated diff --git a/helpers/types.ts b/helpers/types.ts index 39237440..a56e054b 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -36,8 +36,8 @@ export enum EthereumNetworkNames { export enum AavePools { proto = 'proto', - lp = 'lp', matic = 'matic', + amm = 'amm', } export enum eContractid { @@ -220,11 +220,6 @@ export interface iAssetBase { USD: T; REN: T; ENJ: T; - // LpWETH: T; - // LpWBTC: T; - // LpDAI: T; - // LpUSDC: T; - // LpUSDT: T; UniDAIWETH: T; UniWBTCWETH: T; UniAAVEWETH: T; @@ -334,11 +329,6 @@ export enum TokenContractId { YFI = 'YFI', UNI = 'UNI', ENJ = 'ENJ', - // LpWETH = 'LpWETH', - // LpWBTC = 'LpWBTC', - // LpDAI = 'LpDAI', - // LpUSDC = 'LpUSDC', - // LpUSDT = 'LpUSDT', UniDAIWETH = 'UniDAIWETH', UniWBTCWETH = 'UniWBTCWETH', UniAAVEWETH = 'UniAAVEWETH', @@ -426,8 +416,8 @@ export interface iXDaiParamsPerNetwork { export interface iParamsPerPool { [AavePools.proto]: T; - [AavePools.lp]: T; [AavePools.matic]: T; + [AavePools.amm]: T; } export interface iBasicDistributionParams { @@ -502,7 +492,7 @@ export interface IAaveConfiguration extends ICommonConfiguration { ReservesConfig: iAavePoolAssets; } -export interface ILpConfiguration extends ICommonConfiguration { +export interface IAmmConfiguration extends ICommonConfiguration { ReservesConfig: iLpPoolAssets; } diff --git a/markets/lp/commons.ts b/markets/amm/commons.ts similarity index 100% rename from markets/lp/commons.ts rename to markets/amm/commons.ts diff --git a/markets/lp/index.ts b/markets/amm/index.ts similarity index 96% rename from markets/lp/index.ts rename to markets/amm/index.ts index aeb3bbc7..3cf69834 100644 --- a/markets/lp/index.ts +++ b/markets/amm/index.ts @@ -1,5 +1,5 @@ import { oneRay, ZERO_ADDRESS } from '../../helpers/constants'; -import { ILpConfiguration, eEthereumNetwork } from '../../helpers/types'; +import { IAmmConfiguration, eEthereumNetwork } from '../../helpers/types'; import { CommonsConfig } from './commons'; import { @@ -28,9 +28,9 @@ import { // POOL--SPECIFIC PARAMS // ---------------- -export const lpConfig: ILpConfiguration = { +export const AmmConfig: IAmmConfiguration = { ...CommonsConfig, - MarketId: 'Aave LP market', + MarketId: 'Aave AMM market', ProviderId: 2, ReservesConfig: { WETH: strategyWETH, @@ -129,4 +129,4 @@ export const lpConfig: ILpConfiguration = { }, }; -export default lpConfig; +export default AmmConfig; diff --git a/markets/lp/rateStrategies.ts b/markets/amm/rateStrategies.ts similarity index 94% rename from markets/lp/rateStrategies.ts rename to markets/amm/rateStrategies.ts index a91af2ea..26a68309 100644 --- a/markets/lp/rateStrategies.ts +++ b/markets/amm/rateStrategies.ts @@ -3,8 +3,8 @@ import { oneRay } from '../../helpers/constants'; import { IInterestRateStrategyParams } from '../../helpers/types'; // DAIWETH WBTCWETH AAVEWETH BATWETH USDCDAI CRVWETH LINKWETH MKRWETH RENWETH SNXWETH UNIWETH USDCWETH WBTCUSDC YFIWETH -export const rateStrategyLpBase: IInterestRateStrategyParams = { - name: "rateStrategyLpBase", +export const rateStrategyAmmBase: IInterestRateStrategyParams = { + name: "rateStrategyAmmBase", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), diff --git a/markets/lp/reservesConfigs.ts b/markets/amm/reservesConfigs.ts similarity index 92% rename from markets/lp/reservesConfigs.ts rename to markets/amm/reservesConfigs.ts index 21db2a1e..31b1a13c 100644 --- a/markets/lp/reservesConfigs.ts +++ b/markets/amm/reservesConfigs.ts @@ -1,6 +1,6 @@ import { eContractid, IReserveParams} from '../../helpers/types'; import { - rateStrategyLpBase, + rateStrategyAmmBase, rateStrategyStable, rateStrategyBaseOne, } from './rateStrategies'; @@ -67,7 +67,7 @@ export const strategyUSDT: IReserveParams = { }; export const strategyDAIWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -79,7 +79,7 @@ export const strategyDAIWETH: IReserveParams = { }; export const strategyWBTCWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -91,7 +91,7 @@ export const strategyWBTCWETH: IReserveParams = { }; export const strategyAAVEWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -103,7 +103,7 @@ export const strategyAAVEWETH: IReserveParams = { }; export const strategyBATWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -115,7 +115,7 @@ export const strategyBATWETH: IReserveParams = { }; export const strategyUSDCDAI: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -127,7 +127,7 @@ export const strategyUSDCDAI: IReserveParams = { }; export const strategyCRVWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '5000', liquidationThreshold: '6000', liquidationBonus: '11500', @@ -139,7 +139,7 @@ export const strategyCRVWETH: IReserveParams = { }; export const strategyLINKWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -151,7 +151,7 @@ export const strategyLINKWETH: IReserveParams = { }; export const strategyMKRWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -163,7 +163,7 @@ export const strategyMKRWETH: IReserveParams = { }; export const strategyRENWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -175,7 +175,7 @@ export const strategyRENWETH: IReserveParams = { }; export const strategySNXWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '4000', liquidationThreshold: '6000', liquidationBonus: '11500', @@ -187,7 +187,7 @@ export const strategySNXWETH: IReserveParams = { }; export const strategyUNIWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -199,7 +199,7 @@ export const strategyUNIWETH: IReserveParams = { }; export const strategyUSDCWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -211,7 +211,7 @@ export const strategyUSDCWETH: IReserveParams = { }; export const strategyWBTCUSDC: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', liquidationBonus: '11500', @@ -223,7 +223,7 @@ export const strategyWBTCUSDC: IReserveParams = { }; export const strategyYFIWETH: IReserveParams = { - strategy: rateStrategyLpBase, + strategy: rateStrategyAmmBase, baseLTVAsCollateral: '5000', liquidationThreshold: '6000', liquidationBonus: '11500', diff --git a/package-lock.json b/package-lock.json index 129f12e4..e0a68833 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27128,7 +27128,7 @@ "requires": { "underscore": "1.9.1", "web3-core-helpers": "1.2.1", - "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" + "websocket": "websocket@github:web3-js/WebSocket-Node#polyfill/globalThis" } }, "web3-shh": { @@ -39846,7 +39846,7 @@ "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", "dev": true, "requires": { - "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git", + "ethereumjs-abi": "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git", "ethereumjs-util": "^5.1.1" } }, @@ -46846,7 +46846,7 @@ "eth-lib": "0.2.7", "ethereumjs-common": "^1.3.2", "ethereumjs-tx": "^2.1.1", - "scrypt-shim": "github:web3-js/scrypt-shim", + "scrypt-shim": "scrypt-shim@github:web3-js/scrypt-shim", "underscore": "1.9.1", "uuid": "3.3.2", "web3-core": "1.2.2", @@ -47176,7 +47176,7 @@ "requires": { "underscore": "1.9.1", "web3-core-helpers": "1.2.2", - "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" + "websocket": "websocket@github:web3-js/WebSocket-Node#polyfill/globalThis" } }, "web3-shh": { diff --git a/package.json b/package.json index cd067de1..5fd959fa 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "compile": "SKIP_LOAD=true hardhat compile", "console:fork": "MAINNET_FORK=true hardhat console", "test": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-aave/*.spec.ts", - "test-lp": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-lp/*.spec.ts", - "test-lp-scenarios": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-lp/__setup.spec.ts test-suites/test-lp/scenario.spec.ts", + "test-amm": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-amm/*.spec.ts", + "test-amm-scenarios": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-amm/__setup.spec.ts test-suites/test-amm/scenario.spec.ts", "test-scenarios": "npx hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/scenario.spec.ts", "test-repay-with-collateral": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/repay-with-collateral.spec.ts", "test-liquidate-with-collateral": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/flash-liquidation-with-collateral.spec.ts", @@ -35,21 +35,21 @@ "test-stable-and-atokens": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-transfer.spec.ts test-suites/test-aave/stable-token.spec.ts", "test-subgraph:scenarios": "hardhat --network hardhatevm_docker test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/subgraph-scenarios.spec.ts", "test-weth:main": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/weth-gateway.spec.ts", - "test-weth:lp": "hardhat test test-suites/test-lp/__setup.spec.ts test-suites/test-lp/weth-gateway.spec.ts", + "test-weth:amm": "hardhat test test-suites/test-amm/__setup.spec.ts test-suites/test-amm/weth-gateway.spec.ts", "test-uniswap": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/uniswapAdapters*.spec.ts", "test:main:check-list": "MAINNET_FORK=true TS_NODE_TRANSPILE_ONLY=1 hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/mainnet/check-list.spec.ts", "dev:coverage": "buidler compile --force && buidler coverage --network coverage", "aave:evm:dev:migration": "npm run compile && hardhat aave:dev", "aave:docker:full:migration": "npm run compile && npm run hardhat:docker -- aave:mainnet", "aave:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- aave:mainnet --verify", - "lp:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- lp:mainnet --verify", "matic:mumbai:full:migration": "npm run compile && npm run hardhat:mumbai matic:mainnet", "matic:matic:full:migration": "npm run compile && npm run hardhat:matic matic:mainnet", + "amm:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- amm:mainnet --verify", "aave:kovan:full:initialize": "npm run hardhat:kovan -- full:initialize-lending-pool --verify --pool Aave", "aave:ropsten:full:migration": "npm run compile && npm run hardhat:ropsten -- aave:mainnet --verify", "aave:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- aave:mainnet", "aave:fork:main": "npm run compile && MAINNET_FORK=true hardhat aave:mainnet", - "lp:fork:main": "npm run compile && MAINNET_FORK=true hardhat lp:mainnet", + "amm:fork:main": "npm run compile && MAINNET_FORK=true hardhat amm:mainnet", "aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify", "aave:main:full:initialize": "npm run compile && MAINNET_FORK=true full:initialize-tokens --pool Aave", "prettier:check": "npx prettier -c 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test-suites/test-aave/**/*.ts'", diff --git a/tasks/full/2_lending_pool.ts b/tasks/full/2_lending_pool.ts index 5f92b8eb..7e1ba2cb 100644 --- a/tasks/full/2_lending_pool.ts +++ b/tasks/full/2_lending_pool.ts @@ -25,7 +25,7 @@ task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment') const network = DRE.network.name; const poolConfig = loadPoolConfig(pool); const addressesProvider = await getLendingPoolAddressesProvider(); - + const { LendingPool, LendingPoolConfigurator } = poolConfig; // Reuse/deploy lending pool implementation diff --git a/tasks/migrations/lp.mainnet.ts b/tasks/migrations/amm.mainnet.ts similarity index 95% rename from tasks/migrations/lp.mainnet.ts rename to tasks/migrations/amm.mainnet.ts index 97a47ffa..3d0e6c8b 100644 --- a/tasks/migrations/lp.mainnet.ts +++ b/tasks/migrations/amm.mainnet.ts @@ -4,10 +4,10 @@ import { ConfigNames } from '../../helpers/configuration'; import { printContracts } from '../../helpers/misc-utils'; import { usingTenderly } from '../../helpers/tenderly-utils'; -task('lp:mainnet', 'Deploy development enviroment') +task('amm:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') .setAction(async ({ verify }, DRE) => { - const POOL_NAME = ConfigNames.Lp; + const POOL_NAME = ConfigNames.Amm; await DRE.run('set-DRE'); // Prevent loss of gas verifying all the needed ENVs for Etherscan verification diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index 79be455b..c9a54f7f 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -28,6 +28,7 @@ import { deployFlashLiquidationAdapter, authorizeWETHGateway, } from '../../helpers/contracts-deployments'; +import { eEthereumNetwork } from '../../helpers/types'; import { Signer } from 'ethers'; import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types'; import { MintableERC20 } from '../../types/MintableERC20'; diff --git a/test-suites/test-lp/__setup.spec.ts b/test-suites/test-amm/__setup.spec.ts similarity index 93% rename from test-suites/test-lp/__setup.spec.ts rename to test-suites/test-amm/__setup.spec.ts index d359b51e..2ce5ce85 100644 --- a/test-suites/test-lp/__setup.spec.ts +++ b/test-suites/test-amm/__setup.spec.ts @@ -46,7 +46,7 @@ import { } from '../../helpers/oracles-helpers'; import { DRE, waitForTx } from '../../helpers/misc-utils'; import { initReservesByHelper, configureReservesByHelper } from '../../helpers/init-helpers'; -import LpConfig from '../../markets/lp'; +import AmmConfig from '../../markets/amm'; import { ZERO_ADDRESS } from '../../helpers/constants'; import { getLendingPool, @@ -55,16 +55,16 @@ import { } from '../../helpers/contracts-getters'; import { WETH9Mocked } from '../../types/WETH9Mocked'; -const MOCK_USD_PRICE_IN_WEI = LpConfig.ProtocolGlobalParams.MockUsdPriceInWei; -const ALL_ASSETS_INITIAL_PRICES = LpConfig.Mocks.AllAssetsInitialPrices; -const USD_ADDRESS = LpConfig.ProtocolGlobalParams.UsdAddress; -const MOCK_CHAINLINK_AGGREGATORS_PRICES = LpConfig.Mocks.AllAssetsInitialPrices; -const LENDING_RATE_ORACLE_RATES_COMMON = LpConfig.LendingRateOracleRatesCommon; +const MOCK_USD_PRICE_IN_WEI = AmmConfig.ProtocolGlobalParams.MockUsdPriceInWei; +const ALL_ASSETS_INITIAL_PRICES = AmmConfig.Mocks.AllAssetsInitialPrices; +const USD_ADDRESS = AmmConfig.ProtocolGlobalParams.UsdAddress; +const MOCK_CHAINLINK_AGGREGATORS_PRICES = AmmConfig.Mocks.AllAssetsInitialPrices; +const LENDING_RATE_ORACLE_RATES_COMMON = AmmConfig.LendingRateOracleRatesCommon; const deployAllMockTokens = async (deployer: Signer) => { const tokens: { [symbol: string]: MockContract | MintableERC20 | WETH9Mocked } = {}; - const lpConfigData = getReservesConfigByPool(AavePools.lp); + const ammConfigData = getReservesConfigByPool(AavePools.amm); for (const tokenSymbol of Object.keys(TokenContractId)) { if (tokenSymbol === 'WETH') { @@ -74,7 +74,7 @@ const deployAllMockTokens = async (deployer: Signer) => { } let decimals = 18; - let configData = (lpConfigData)[tokenSymbol]; + let configData = (ammConfigData)[tokenSymbol]; if (!configData) { decimals = 18; @@ -97,7 +97,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const mockTokens = await deployAllMockTokens(deployer); - const addressesProvider = await deployLendingPoolAddressesProvider(LpConfig.MarketId); + const addressesProvider = await deployLendingPoolAddressesProvider(AmmConfig.MarketId); await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin)); //setting users[1] as emergency admin, which is in position 2 in the DRE addresses list @@ -229,7 +229,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { aaveAdmin ); - const reservesParams = getReservesConfigByPool(AavePools.lp); + const reservesParams = getReservesConfigByPool(AavePools.amm); const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address); @@ -238,7 +238,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { console.log('Initialize configuration'); - const config = loadPoolConfig(ConfigNames.Lp); + const config = loadPoolConfig(ConfigNames.Amm); const { ATokenNamePrefix, @@ -294,7 +294,7 @@ before(async () => { const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; if (MAINNET_FORK) { - await rawBRE.run('lp:mainnet'); + await rawBRE.run('amm:mainnet'); } else { console.log('-> Deploying test environment...'); await buildTestEnv(deployer, secondaryWallet); diff --git a/test-suites/test-lp/addresses-provider-registry.spec.ts b/test-suites/test-amm/addresses-provider-registry.spec.ts similarity index 100% rename from test-suites/test-lp/addresses-provider-registry.spec.ts rename to test-suites/test-amm/addresses-provider-registry.spec.ts diff --git a/test-suites/test-lp/atoken-modifiers.spec.ts b/test-suites/test-amm/atoken-modifiers.spec.ts similarity index 100% rename from test-suites/test-lp/atoken-modifiers.spec.ts rename to test-suites/test-amm/atoken-modifiers.spec.ts diff --git a/test-suites/test-lp/atoken-permit.spec.ts b/test-suites/test-amm/atoken-permit.spec.ts similarity index 100% rename from test-suites/test-lp/atoken-permit.spec.ts rename to test-suites/test-amm/atoken-permit.spec.ts diff --git a/test-suites/test-lp/atoken-transfer.spec.ts b/test-suites/test-amm/atoken-transfer.spec.ts similarity index 98% rename from test-suites/test-lp/atoken-transfer.spec.ts rename to test-suites/test-amm/atoken-transfer.spec.ts index 9d1b8359..0290f941 100644 --- a/test-suites/test-lp/atoken-transfer.spec.ts +++ b/test-suites/test-amm/atoken-transfer.spec.ts @@ -4,7 +4,7 @@ import { expect } from 'chai'; import { ethers } from 'ethers'; import { RateMode, ProtocolErrors } from '../../helpers/types'; import { makeSuite, TestEnv } from './helpers/make-suite'; -import { CommonsConfig } from '../../markets/lp/commons'; +import { CommonsConfig } from '../../markets/amm/commons'; const AAVE_REFERRAL = CommonsConfig.ProtocolGlobalParams.AaveReferral; diff --git a/test-suites/test-lp/configurator.spec.ts b/test-suites/test-amm/configurator.spec.ts similarity index 99% rename from test-suites/test-lp/configurator.spec.ts rename to test-suites/test-amm/configurator.spec.ts index f4557791..e4e3f4fa 100644 --- a/test-suites/test-lp/configurator.spec.ts +++ b/test-suites/test-amm/configurator.spec.ts @@ -2,7 +2,7 @@ import { TestEnv, makeSuite } from './helpers/make-suite'; import { APPROVAL_AMOUNT_LENDING_POOL, RAY } from '../../helpers/constants'; import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; import { ProtocolErrors } from '../../helpers/types'; -import { strategyWETH } from '../../markets/lp/reservesConfigs'; +import { strategyWETH } from '../../markets/amm/reservesConfigs'; const { expect } = require('chai'); diff --git a/test-suites/test-lp/delegation-aware-atoken.spec.ts b/test-suites/test-amm/delegation-aware-atoken.spec.ts similarity index 96% rename from test-suites/test-lp/delegation-aware-atoken.spec.ts rename to test-suites/test-amm/delegation-aware-atoken.spec.ts index aeaf4499..73ca6883 100644 --- a/test-suites/test-lp/delegation-aware-atoken.spec.ts +++ b/test-suites/test-amm/delegation-aware-atoken.spec.ts @@ -20,7 +20,7 @@ import { import { DelegationAwareATokenFactory } from '../../types'; import { DelegationAwareAToken } from '../../types/DelegationAwareAToken'; import { MintableDelegationERC20 } from '../../types/MintableDelegationERC20'; -import LpConfig from '../../markets/lp'; +import AmmConfig from '../../markets/amm'; const { parseEther } = ethers.utils; @@ -35,7 +35,7 @@ makeSuite('AToken: underlying delegation', (testEnv: TestEnv) => { delegationERC20 = await deployMintableDelegationERC20(['DEL', 'DEL', '18']); delegationAToken = await deployDelegationAwareAToken( - [pool.address, delegationERC20.address, await getTreasuryAddress(LpConfig), ZERO_ADDRESS, 'aDEL', 'aDEL'], + [pool.address, delegationERC20.address, await getTreasuryAddress(AmmConfig), ZERO_ADDRESS, 'aDEL', 'aDEL'], false ); diff --git a/test-suites/test-lp/flashloan.spec.ts b/test-suites/test-amm/flashloan.spec.ts similarity index 100% rename from test-suites/test-lp/flashloan.spec.ts rename to test-suites/test-amm/flashloan.spec.ts diff --git a/test-suites/test-lp/helpers/actions.ts b/test-suites/test-amm/helpers/actions.ts similarity index 100% rename from test-suites/test-lp/helpers/actions.ts rename to test-suites/test-amm/helpers/actions.ts diff --git a/test-suites/test-lp/helpers/almost-equal.ts b/test-suites/test-amm/helpers/almost-equal.ts similarity index 100% rename from test-suites/test-lp/helpers/almost-equal.ts rename to test-suites/test-amm/helpers/almost-equal.ts diff --git a/test-suites/test-lp/helpers/make-suite.ts b/test-suites/test-amm/helpers/make-suite.ts similarity index 98% rename from test-suites/test-lp/helpers/make-suite.ts rename to test-suites/test-amm/helpers/make-suite.ts index c65f0df0..71d96bf5 100644 --- a/test-suites/test-lp/helpers/make-suite.ts +++ b/test-suites/test-amm/helpers/make-suite.ts @@ -36,7 +36,7 @@ import { getParamPerNetwork } from '../../../helpers/contracts-helpers'; import { WETH9Mocked } from '../../../types/WETH9Mocked'; import { WETHGateway } from '../../../types/WETHGateway'; import { solidity } from 'ethereum-waffle'; -import { lpConfig } from '../../../markets/lp'; +import { AmmConfig } from '../../../markets/amm'; import { FlashLiquidationAdapter } from '../../../types'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { usingTenderly } from '../../../helpers/tenderly-utils'; @@ -118,7 +118,7 @@ export async function initializeMakeSuite() { if (process.env.MAINNET_FORK === 'true') { testEnv.registry = await getLendingPoolAddressesProviderRegistry( - getParamPerNetwork(lpConfig.ProviderRegistry, eEthereumNetwork.main) + getParamPerNetwork(AmmConfig.ProviderRegistry, eEthereumNetwork.main) ); } else { testEnv.registry = await getLendingPoolAddressesProviderRegistry(); diff --git a/test-suites/test-lp/helpers/scenario-engine.ts b/test-suites/test-amm/helpers/scenario-engine.ts similarity index 100% rename from test-suites/test-lp/helpers/scenario-engine.ts rename to test-suites/test-amm/helpers/scenario-engine.ts diff --git a/test-suites/test-lp/helpers/scenarios/borrow-negatives.json b/test-suites/test-amm/helpers/scenarios/borrow-negatives.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/borrow-negatives.json rename to test-suites/test-amm/helpers/scenarios/borrow-negatives.json diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json b/test-suites/test-amm/helpers/scenarios/borrow-repay-stable.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/borrow-repay-stable.json rename to test-suites/test-amm/helpers/scenarios/borrow-repay-stable.json diff --git a/test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json b/test-suites/test-amm/helpers/scenarios/borrow-repay-variable.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/borrow-repay-variable.json rename to test-suites/test-amm/helpers/scenarios/borrow-repay-variable.json diff --git a/test-suites/test-lp/helpers/scenarios/credit-delegation.json b/test-suites/test-amm/helpers/scenarios/credit-delegation.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/credit-delegation.json rename to test-suites/test-amm/helpers/scenarios/credit-delegation.json diff --git a/test-suites/test-lp/helpers/scenarios/deposit.json b/test-suites/test-amm/helpers/scenarios/deposit.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/deposit.json rename to test-suites/test-amm/helpers/scenarios/deposit.json diff --git a/test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json b/test-suites/test-amm/helpers/scenarios/rebalance-stable-rate.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/rebalance-stable-rate.json rename to test-suites/test-amm/helpers/scenarios/rebalance-stable-rate.json diff --git a/test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json b/test-suites/test-amm/helpers/scenarios/set-use-as-collateral.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/set-use-as-collateral.json rename to test-suites/test-amm/helpers/scenarios/set-use-as-collateral.json diff --git a/test-suites/test-lp/helpers/scenarios/swap-rate-mode.json b/test-suites/test-amm/helpers/scenarios/swap-rate-mode.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/swap-rate-mode.json rename to test-suites/test-amm/helpers/scenarios/swap-rate-mode.json diff --git a/test-suites/test-lp/helpers/scenarios/withdraw-negatives.json b/test-suites/test-amm/helpers/scenarios/withdraw-negatives.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/withdraw-negatives.json rename to test-suites/test-amm/helpers/scenarios/withdraw-negatives.json diff --git a/test-suites/test-lp/helpers/scenarios/withdraw.json b/test-suites/test-amm/helpers/scenarios/withdraw.json similarity index 100% rename from test-suites/test-lp/helpers/scenarios/withdraw.json rename to test-suites/test-amm/helpers/scenarios/withdraw.json diff --git a/test-suites/test-lp/helpers/utils/calculations.ts b/test-suites/test-amm/helpers/utils/calculations.ts similarity index 100% rename from test-suites/test-lp/helpers/utils/calculations.ts rename to test-suites/test-amm/helpers/utils/calculations.ts diff --git a/test-suites/test-lp/helpers/utils/helpers.ts b/test-suites/test-amm/helpers/utils/helpers.ts similarity index 100% rename from test-suites/test-lp/helpers/utils/helpers.ts rename to test-suites/test-amm/helpers/utils/helpers.ts diff --git a/test-suites/test-lp/helpers/utils/interfaces/index.ts b/test-suites/test-amm/helpers/utils/interfaces/index.ts similarity index 100% rename from test-suites/test-lp/helpers/utils/interfaces/index.ts rename to test-suites/test-amm/helpers/utils/interfaces/index.ts diff --git a/test-suites/test-lp/helpers/utils/math.ts b/test-suites/test-amm/helpers/utils/math.ts similarity index 100% rename from test-suites/test-lp/helpers/utils/math.ts rename to test-suites/test-amm/helpers/utils/math.ts diff --git a/test-suites/test-lp/lending-pool-addresses-provider.spec.ts b/test-suites/test-amm/lending-pool-addresses-provider.spec.ts similarity index 100% rename from test-suites/test-lp/lending-pool-addresses-provider.spec.ts rename to test-suites/test-amm/lending-pool-addresses-provider.spec.ts diff --git a/test-suites/test-lp/liquidation-atoken.spec.ts b/test-suites/test-amm/liquidation-atoken.spec.ts similarity index 100% rename from test-suites/test-lp/liquidation-atoken.spec.ts rename to test-suites/test-amm/liquidation-atoken.spec.ts diff --git a/test-suites/test-lp/liquidation-underlying.spec.ts b/test-suites/test-amm/liquidation-underlying.spec.ts similarity index 99% rename from test-suites/test-lp/liquidation-underlying.spec.ts rename to test-suites/test-amm/liquidation-underlying.spec.ts index 7bc78dad..e44a2d80 100644 --- a/test-suites/test-lp/liquidation-underlying.spec.ts +++ b/test-suites/test-amm/liquidation-underlying.spec.ts @@ -7,7 +7,7 @@ import { makeSuite } from './helpers/make-suite'; import { ProtocolErrors, RateMode } from '../../helpers/types'; import { calcExpectedVariableDebtTokenBalance } from './helpers/utils/calculations'; import { getReserveData, getUserData } from './helpers/utils/helpers'; -import { CommonsConfig } from '../../markets/lp/commons'; +import { CommonsConfig } from '../../markets/amm/commons'; import { parseEther } from 'ethers/lib/utils'; diff --git a/test-suites/test-lp/mainnet/check-list.spec.ts b/test-suites/test-amm/mainnet/check-list.spec.ts similarity index 100% rename from test-suites/test-lp/mainnet/check-list.spec.ts rename to test-suites/test-amm/mainnet/check-list.spec.ts diff --git a/test-suites/test-lp/pausable-functions.spec.ts b/test-suites/test-amm/pausable-functions.spec.ts similarity index 100% rename from test-suites/test-lp/pausable-functions.spec.ts rename to test-suites/test-amm/pausable-functions.spec.ts diff --git a/test-suites/test-lp/pool-modifiers.spec.ts b/test-suites/test-amm/pool-modifiers.spec.ts similarity index 100% rename from test-suites/test-lp/pool-modifiers.spec.ts rename to test-suites/test-amm/pool-modifiers.spec.ts diff --git a/test-suites/test-lp/rate-strategy.spec.ts b/test-suites/test-amm/rate-strategy.spec.ts similarity index 100% rename from test-suites/test-lp/rate-strategy.spec.ts rename to test-suites/test-amm/rate-strategy.spec.ts diff --git a/test-suites/test-lp/scenario.spec.ts b/test-suites/test-amm/scenario.spec.ts similarity index 93% rename from test-suites/test-lp/scenario.spec.ts rename to test-suites/test-amm/scenario.spec.ts index 99bed044..f9c4d78b 100644 --- a/test-suites/test-lp/scenario.spec.ts +++ b/test-suites/test-amm/scenario.spec.ts @@ -8,7 +8,7 @@ import { getReservesConfigByPool } from '../../helpers/configuration'; import { AavePools, iLpPoolAssets, IReserveParams } from '../../helpers/types'; import { executeStory } from './helpers/scenario-engine'; -const scenarioFolder = './test-suites/test-lp/helpers/scenarios/'; +const scenarioFolder = './test-suites/test-amm/helpers/scenarios/'; const selectedScenarios: string[] = []; @@ -25,7 +25,7 @@ fs.readdirSync(scenarioFolder).forEach((file) => { actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage calculationsConfiguration.reservesParams = >( - getReservesConfigByPool(AavePools.lp) + getReservesConfigByPool(AavePools.amm) ); }); after('Reset', () => { diff --git a/test-suites/test-lp/stable-rate-economy.spec.ts b/test-suites/test-amm/stable-rate-economy.spec.ts similarity index 100% rename from test-suites/test-lp/stable-rate-economy.spec.ts rename to test-suites/test-amm/stable-rate-economy.spec.ts diff --git a/test-suites/test-lp/stable-token.spec.ts b/test-suites/test-amm/stable-token.spec.ts similarity index 100% rename from test-suites/test-lp/stable-token.spec.ts rename to test-suites/test-amm/stable-token.spec.ts diff --git a/test-suites/test-lp/subgraph-scenarios.spec.ts b/test-suites/test-amm/subgraph-scenarios.spec.ts similarity index 96% rename from test-suites/test-lp/subgraph-scenarios.spec.ts rename to test-suites/test-amm/subgraph-scenarios.spec.ts index 24e119f1..a622eb34 100644 --- a/test-suites/test-lp/subgraph-scenarios.spec.ts +++ b/test-suites/test-amm/subgraph-scenarios.spec.ts @@ -19,7 +19,7 @@ makeSuite('Subgraph scenario tests', async (testEnv) => { actionsConfiguration.skipIntegrityCheck = false; //set this to true to execute solidity-coverage calculationsConfiguration.reservesParams = >( - getReservesConfigByPool(AavePools.lp) + getReservesConfigByPool(AavePools.amm) ); }); after('Reset', () => { diff --git a/test-suites/test-lp/uniswapAdapters.base.spec.ts b/test-suites/test-amm/uniswapAdapters.base.spec.ts similarity index 100% rename from test-suites/test-lp/uniswapAdapters.base.spec.ts rename to test-suites/test-amm/uniswapAdapters.base.spec.ts diff --git a/test-suites/test-lp/uniswapAdapters.flashLiquidation.spec.ts b/test-suites/test-amm/uniswapAdapters.flashLiquidation.spec.ts similarity index 100% rename from test-suites/test-lp/uniswapAdapters.flashLiquidation.spec.ts rename to test-suites/test-amm/uniswapAdapters.flashLiquidation.spec.ts diff --git a/test-suites/test-lp/uniswapAdapters.liquiditySwap.spec.ts b/test-suites/test-amm/uniswapAdapters.liquiditySwap.spec.ts similarity index 100% rename from test-suites/test-lp/uniswapAdapters.liquiditySwap.spec.ts rename to test-suites/test-amm/uniswapAdapters.liquiditySwap.spec.ts diff --git a/test-suites/test-lp/uniswapAdapters.repay.spec.ts b/test-suites/test-amm/uniswapAdapters.repay.spec.ts similarity index 100% rename from test-suites/test-lp/uniswapAdapters.repay.spec.ts rename to test-suites/test-amm/uniswapAdapters.repay.spec.ts diff --git a/test-suites/test-lp/upgradeability.spec.ts b/test-suites/test-amm/upgradeability.spec.ts similarity index 100% rename from test-suites/test-lp/upgradeability.spec.ts rename to test-suites/test-amm/upgradeability.spec.ts diff --git a/test-suites/test-lp/variable-debt-token.spec.ts b/test-suites/test-amm/variable-debt-token.spec.ts similarity index 100% rename from test-suites/test-lp/variable-debt-token.spec.ts rename to test-suites/test-amm/variable-debt-token.spec.ts diff --git a/test-suites/test-lp/weth-gateway.spec.ts b/test-suites/test-amm/weth-gateway.spec.ts similarity index 100% rename from test-suites/test-lp/weth-gateway.spec.ts rename to test-suites/test-amm/weth-gateway.spec.ts From b4936499a74c1d0ef58cde0a127ad40dac08b207 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Tue, 23 Feb 2021 10:59:20 -0500 Subject: [PATCH 154/219] Fixed resuable addresses to match implementations --- markets/amm/commons.ts | 6 +++--- markets/matic/commons.ts | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/markets/amm/commons.ts b/markets/amm/commons.ts index bce33b98..f8608416 100644 --- a/markets/amm/commons.ts +++ b/markets/amm/commons.ts @@ -141,8 +141,8 @@ export const CommonsConfig: ICommonConfiguration = { LendingRateOracle: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', - [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '',//'0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a', // Need to re-deploy because of onlyOwner + [eEthereumNetwork.buidlerevm]: '',// Updated to match Kovan deployment + [eEthereumNetwork.kovan]: '0xd00Bd28FAdDa9d5658D1D4e0c151973146C7A533',//'0xE48F95873855bfd97BF89572DDf5cBC44D9c545b' [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', [eEthereumNetwork.main]: '', //'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', // Need to re-deploy because of onlyOwner [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', @@ -178,7 +178,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.kovan]: '0x1c4A1cC35A477aa1cF35DF671d93ACc04d8131E0', [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '', [eEthereumNetwork.tenderlyMain]: '', diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index 109bda77..42b269b0 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -68,11 +68,11 @@ export const CommonsConfig: ICommonConfiguration = { }, LendingPool: { [ePolygonNetwork.mumbai]: '', - [ePolygonNetwork.matic]: '0x15Ec48a46d2D26cf4ADf5A39123E4c75e6887fE0', + [ePolygonNetwork.matic]: '0xABdC61Cd16e5111f335f4135B7A0e65Cc7F86327', }, LendingPoolConfigurator: { [ePolygonNetwork.mumbai]: '', - [ePolygonNetwork.matic]: '0x268F48E09c72f6008DA50D6465a174C10167918e', + [ePolygonNetwork.matic]: '0x17c4A170FFF882862F656597889016D3a6073534', }, EmergencyAdminIndex: 1, ProviderRegistry: { @@ -89,7 +89,7 @@ export const CommonsConfig: ICommonConfiguration = { }, LendingPoolCollateralManager: { [ePolygonNetwork.mumbai]: '', - [ePolygonNetwork.matic]: '', + [ePolygonNetwork.matic]: '0x9Af76e0575D139570D3B4c821567Fe935E8c25C5', }, TokenDistributor: { [ePolygonNetwork.mumbai]: '', @@ -97,11 +97,11 @@ export const CommonsConfig: ICommonConfiguration = { }, WethGateway: { [ePolygonNetwork.mumbai]: '', - [ePolygonNetwork.matic]: '0x4fAfE6704a78e21Fc43C01bEb153607604F6768a', + [ePolygonNetwork.matic]: '0x15A46f5073789b7D16F6F46632aE50Bae838d938', }, AaveOracle: { [ePolygonNetwork.mumbai]: '', - [ePolygonNetwork.matic]: '', + [ePolygonNetwork.matic]: '0x1B38fa90596F2C25bCf1B193A6c6a718349AFDfC', }, FallbackOracle: { [ePolygonNetwork.mumbai]: ZERO_ADDRESS, From 735fc5c6c76975ee58917e42c9a4956348ea271a Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Tue, 23 Feb 2021 11:05:46 -0500 Subject: [PATCH 155/219] Removed useless space --- tasks/full/2_lending_pool.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/full/2_lending_pool.ts b/tasks/full/2_lending_pool.ts index 7e1ba2cb..5f92b8eb 100644 --- a/tasks/full/2_lending_pool.ts +++ b/tasks/full/2_lending_pool.ts @@ -25,7 +25,7 @@ task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment') const network = DRE.network.name; const poolConfig = loadPoolConfig(pool); const addressesProvider = await getLendingPoolAddressesProvider(); - + const { LendingPool, LendingPoolConfigurator } = poolConfig; // Reuse/deploy lending pool implementation From b2d344e18933b48a3421ae4efa6ec8cec3de75c1 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 24 Feb 2021 10:55:52 -0500 Subject: [PATCH 156/219] Changed USDCDAI to DAIUSDC to fit pair order --- helpers/constants.ts | 2 +- helpers/types.ts | 6 +++--- markets/amm/commons.ts | 8 ++++---- markets/amm/index.ts | 10 +++++----- markets/amm/rateStrategies.ts | 2 +- markets/amm/reservesConfigs.ts | 2 +- test-suites/test-aave/__setup.spec.ts | 2 +- test-suites/test-amm/__setup.spec.ts | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/helpers/constants.ts b/helpers/constants.ts index 9a223bd6..31b255a1 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -54,7 +54,7 @@ export const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(), UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(), - UniUSDCDAI: oneEther.multipliedBy('22.407436').toFixed(), + UniDAIUSDC: oneEther.multipliedBy('22.407436').toFixed(), UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(), UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(), UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(), diff --git a/helpers/types.ts b/helpers/types.ts index a56e054b..d0a5fb43 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -224,7 +224,7 @@ export interface iAssetBase { UniWBTCWETH: T; UniAAVEWETH: T; UniBATWETH: T; - UniUSDCDAI: T; + UniDAIUSDC: T; UniCRVWETH: T; UniLINKWETH: T; UniMKRWETH: T; @@ -278,7 +278,7 @@ export type iLpPoolAssets = Pick< | 'UniWBTCWETH' | 'UniAAVEWETH' | 'UniBATWETH' - | 'UniUSDCDAI' + | 'UniDAIUSDC' | 'UniCRVWETH' | 'UniLINKWETH' | 'UniMKRWETH' @@ -333,7 +333,7 @@ export enum TokenContractId { UniWBTCWETH = 'UniWBTCWETH', UniAAVEWETH = 'UniAAVEWETH', UniBATWETH = 'UniBATWETH', - UniUSDCDAI = 'UniUSDCDAI', + UniDAIUSDC = 'UniDAIUSDC', UniCRVWETH = 'UniCRVWETH', UniLINKWETH = 'UniLINKWETH', UniMKRWETH = 'UniMKRWETH', diff --git a/markets/amm/commons.ts b/markets/amm/commons.ts index f8608416..f0dadf97 100644 --- a/markets/amm/commons.ts +++ b/markets/amm/commons.ts @@ -60,7 +60,7 @@ export const CommonsConfig: ICommonConfiguration = { UniBATWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniUSDCDAI: { + UniDAIUSDC: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, UniCRVWETH: { @@ -223,7 +223,7 @@ export const CommonsConfig: ICommonConfiguration = { UniWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', UniAAVEWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', UniBATWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', - UniUSDCDAI: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + UniDAIUSDC: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', UniCRVWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', UniLINKWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', UniMKRWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', @@ -247,7 +247,7 @@ export const CommonsConfig: ICommonConfiguration = { UniWBTCWETH: ZERO_ADDRESS, UniAAVEWETH: ZERO_ADDRESS, UniBATWETH: ZERO_ADDRESS, - UniUSDCDAI: ZERO_ADDRESS, + UniDAIUSDC: ZERO_ADDRESS, UniCRVWETH: ZERO_ADDRESS, UniLINKWETH: ZERO_ADDRESS, UniMKRWETH: ZERO_ADDRESS, @@ -269,7 +269,7 @@ export const CommonsConfig: ICommonConfiguration = { UniWBTCWETH: ZERO_ADDRESS, UniAAVEWETH: ZERO_ADDRESS, UniBATWETH: ZERO_ADDRESS, - UniUSDCDAI: ZERO_ADDRESS, + UniDAIUSDC: ZERO_ADDRESS, UniCRVWETH: ZERO_ADDRESS, UniLINKWETH: ZERO_ADDRESS, UniMKRWETH: ZERO_ADDRESS, diff --git a/markets/amm/index.ts b/markets/amm/index.ts index 3cf69834..705e4be3 100644 --- a/markets/amm/index.ts +++ b/markets/amm/index.ts @@ -12,7 +12,7 @@ import { strategyDAIWETH, strategyAAVEWETH, strategyBATWETH, - strategyUSDCDAI, + strategyDAIUSDC, strategyCRVWETH, strategyLINKWETH, strategyMKRWETH, @@ -42,7 +42,7 @@ export const AmmConfig: IAmmConfiguration = { UniWBTCWETH: strategyWBTCWETH, UniAAVEWETH: strategyAAVEWETH, UniBATWETH: strategyBATWETH, - UniUSDCDAI: strategyUSDCDAI, + UniDAIUSDC: strategyDAIUSDC, UniCRVWETH: strategyCRVWETH, UniLINKWETH: strategyLINKWETH, UniMKRWETH: strategyMKRWETH, @@ -68,7 +68,7 @@ export const AmmConfig: IAmmConfiguration = { UniWBTCWETH: '0x796d562B1dF5b9dc85A4612187B6f29Ed213d960', UniAAVEWETH: '0x657A7B8b46F35C5C6583AEF43824744B236EF826', UniBATWETH: '0xf8CEBA8b16579956B3aE4B5D09002a30f873F783', - UniUSDCDAI: '0x8e80b7a7531c276dD1dBEC2f1Cc281c11c859e62', + UniDAIUSDC: '0x8e80b7a7531c276dD1dBEC2f1Cc281c11c859e62', UniCRVWETH: '0x9c31b7538467bF0b01e6d5fA789e66Ce540a521e', UniLINKWETH: '0x5Acab7f8B79620ec7127A96E5D8837d2124D5D7c', UniMKRWETH: '0xB0C6EC5d58ddbF4cd1e419A56a19924E9904e4Dd', @@ -92,7 +92,7 @@ export const AmmConfig: IAmmConfiguration = { UniWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', UniAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f', UniBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838', - UniUSDCDAI: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', + UniDAIUSDC: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', UniCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE', UniLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974', UniMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225', @@ -114,7 +114,7 @@ export const AmmConfig: IAmmConfiguration = { UniWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940', UniAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f', UniBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838', - UniUSDCDAI: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', + UniDAIUSDC: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', UniCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE', UniLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974', UniMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225', diff --git a/markets/amm/rateStrategies.ts b/markets/amm/rateStrategies.ts index 26a68309..a4a05300 100644 --- a/markets/amm/rateStrategies.ts +++ b/markets/amm/rateStrategies.ts @@ -2,7 +2,7 @@ import BigNumber from 'bignumber.js'; import { oneRay } from '../../helpers/constants'; import { IInterestRateStrategyParams } from '../../helpers/types'; -// DAIWETH WBTCWETH AAVEWETH BATWETH USDCDAI CRVWETH LINKWETH MKRWETH RENWETH SNXWETH UNIWETH USDCWETH WBTCUSDC YFIWETH +// DAIWETH WBTCWETH AAVEWETH BATWETH DAIUSDC CRVWETH LINKWETH MKRWETH RENWETH SNXWETH UNIWETH USDCWETH WBTCUSDC YFIWETH export const rateStrategyAmmBase: IInterestRateStrategyParams = { name: "rateStrategyAmmBase", optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), diff --git a/markets/amm/reservesConfigs.ts b/markets/amm/reservesConfigs.ts index 31b1a13c..b4143653 100644 --- a/markets/amm/reservesConfigs.ts +++ b/markets/amm/reservesConfigs.ts @@ -114,7 +114,7 @@ export const strategyBATWETH: IReserveParams = { reserveFactor: '1500' }; -export const strategyUSDCDAI: IReserveParams = { +export const strategyDAIUSDC: IReserveParams = { strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', liquidationThreshold: '7000', diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index c9a54f7f..b157610f 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -176,7 +176,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { UniWBTCWETH: mockTokens.UniWBTCWETH.address, UniAAVEWETH: mockTokens.UniAAVEWETH.address, UniBATWETH: mockTokens.UniBATWETH.address, - UniUSDCDAI: mockTokens.UniUSDCDAI.address, + UniDAIUSDC: mockTokens.UniDAIUSDC.address, UniCRVWETH: mockTokens.UniCRVWETH.address, UniLINKWETH: mockTokens.UniLINKWETH.address, UniMKRWETH: mockTokens.UniMKRWETH.address, diff --git a/test-suites/test-amm/__setup.spec.ts b/test-suites/test-amm/__setup.spec.ts index 2ce5ce85..7d55702e 100644 --- a/test-suites/test-amm/__setup.spec.ts +++ b/test-suites/test-amm/__setup.spec.ts @@ -175,7 +175,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { UniWBTCWETH: mockTokens.UniWBTCWETH.address, UniAAVEWETH: mockTokens.UniAAVEWETH.address, UniBATWETH: mockTokens.UniBATWETH.address, - UniUSDCDAI: mockTokens.UniUSDCDAI.address, + UniDAIUSDC: mockTokens.UniDAIUSDC.address, UniCRVWETH: mockTokens.UniCRVWETH.address, UniLINKWETH: mockTokens.UniLINKWETH.address, UniMKRWETH: mockTokens.UniMKRWETH.address, From 53139ce9914b5624d021599c6a87212728d8458f Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 24 Feb 2021 16:42:41 -0500 Subject: [PATCH 157/219] Removed useless space --- helpers/contracts-helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index d025b694..b15ce276 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -183,8 +183,8 @@ export const getParamPerPool = ({ proto, amm }: iParamsPerPool, pool: Aave switch (pool) { case AavePools.proto: return proto; - case AavePools.amm: - return amm; + case AavePools.amm: + return amm; default: return proto; } From 46be3c6e8aa9ad64e7d7bfee610afc3dbc19f485 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 24 Feb 2021 16:43:57 -0500 Subject: [PATCH 158/219] Clarified comment --- 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 f0014347..7d8f7eb4 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -105,7 +105,7 @@ export const initReservesByHelper = async ( let stableDebtTokenImplementationAddress = ''; let variableDebtTokenImplementationAddress = ''; - // NOT WORKING ON MATIC + // NOT WORKING ON MATIC, DEPLOYING INDIVIDUAL IMPLs INSTEAD // const tx1 = await waitForTx( // await stableAndVariableDeployer.initDeployment([ZERO_ADDRESS], ["1"]) // ); From 6508aa61279668ac30db313d0bbf1b36b083a73d Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 24 Feb 2021 16:44:45 -0500 Subject: [PATCH 159/219] Fixed small error --- helpers/contracts-helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index b15ce276..eb087500 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -167,7 +167,7 @@ export const getParamPerNetwork = (param: iParamsPerNetwork, network: eNet case eEthereumNetwork.ropsten: return ropsten; case eEthereumNetwork.main: - return mumbai; + return main; case eEthereumNetwork.tenderlyMain: return tenderlyMain; case ePolygonNetwork.matic: From 71127888a6035384cf83a6277d216423ba7485ac Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 24 Feb 2021 16:49:23 -0500 Subject: [PATCH 160/219] Updated Matic deployment script --- helpers/contracts-helpers.ts | 4 +++- tasks/migrations/matic.mainnet.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index eb087500..d7e50664 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -179,12 +179,14 @@ export const getParamPerNetwork = (param: iParamsPerNetwork, network: eNet } }; -export const getParamPerPool = ({ proto, amm }: iParamsPerPool, pool: AavePools) => { +export const getParamPerPool = ({ proto, amm, matic }: iParamsPerPool, pool: AavePools) => { switch (pool) { case AavePools.proto: return proto; case AavePools.amm: return amm; + case AavePools.matic: + return matic; default: return proto; } diff --git a/tasks/migrations/matic.mainnet.ts b/tasks/migrations/matic.mainnet.ts index 0c8efe3c..970fbfc9 100644 --- a/tasks/migrations/matic.mainnet.ts +++ b/tasks/migrations/matic.mainnet.ts @@ -21,7 +21,7 @@ task('matic:mainnet', 'Deploy development enviroment') await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); console.log('2. Deploy lending pool'); - await DRE.run('full: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 }); From fb3c0fc119e5de3f9620cf063ae17d5a677b1200 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 24 Feb 2021 17:36:16 -0500 Subject: [PATCH 161/219] Added amm:main:full:migration task --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 5fd959fa..2b3703c4 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "amm:fork:main": "npm run compile && MAINNET_FORK=true hardhat amm:mainnet", "aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify", "aave:main:full:initialize": "npm run compile && MAINNET_FORK=true full:initialize-tokens --pool Aave", + "amm:main:full:migration": "npm run compile && npm run hardhat:main -- amm:mainnet --verify", "prettier:check": "npx prettier -c 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test-suites/test-aave/**/*.ts'", "prettier:write": "prettier --write 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test-suites/test-aave/**/*.ts'", "ci:test": "npm run compile && npm run test", From ce7d011e207a7b01c6d6d6f71903bac03f82ba8b Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Wed, 24 Feb 2021 17:58:20 -0500 Subject: [PATCH 162/219] Initial setup for BptBALWETH --- helpers/constants.ts | 1 + helpers/types.ts | 3 +++ markets/amm/commons.ts | 6 ++++++ markets/amm/index.ts | 5 +++++ markets/amm/reservesConfigs.ts | 14 +++++++++++++- test-suites/test-aave/__setup.spec.ts | 1 + test-suites/test-amm/__setup.spec.ts | 1 + 7 files changed, 30 insertions(+), 1 deletion(-) diff --git a/helpers/constants.ts b/helpers/constants.ts index 31b255a1..f9ec7f2b 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -65,6 +65,7 @@ export const MOCK_CHAINLINK_AGGREGATORS_PRICES = { UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(), UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(), BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(), + BptBALWETH: oneEther.multipliedBy('22.407436').toFixed(), WMATIC: oneEther.multipliedBy('0.003620948469').toFixed(), STAKE: oneEther.multipliedBy('0.003620948469').toFixed(), USD: '5848466240000000', diff --git a/helpers/types.ts b/helpers/types.ts index d0a5fb43..a564fc13 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -235,6 +235,7 @@ export interface iAssetBase { UniWBTCUSDC: T; UniYFIWETH: T; BptWBTCWETH: T; + BptBALWETH: T; WMATIC: T; STAKE: T; } @@ -289,6 +290,7 @@ export type iLpPoolAssets = Pick< | 'UniWBTCUSDC' | 'UniYFIWETH' | 'BptWBTCWETH' + | 'BptBALWETH' >; export type iMaticPoolAssets = Pick< @@ -344,6 +346,7 @@ export enum TokenContractId { UniWBTCUSDC = 'UniWBTCUSDC', UniYFIWETH = 'UniYFIWETH', BptWBTCWETH = 'BptWBTCWETH', + BptBALWETH = 'BptBALWETH', WMATIC = 'WMATIC', STAKE = 'STAKE', } diff --git a/markets/amm/commons.ts b/markets/amm/commons.ts index f0dadf97..ce8614a8 100644 --- a/markets/amm/commons.ts +++ b/markets/amm/commons.ts @@ -93,6 +93,9 @@ export const CommonsConfig: ICommonConfiguration = { BptWBTCWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, + BptBALWETH: { + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + } }, // ---------------- // COMMON PROTOCOL ADDRESSES ACROSS POOLS @@ -234,6 +237,7 @@ export const CommonsConfig: ICommonConfiguration = { UniWBTCUSDC: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', UniYFIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', BptWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + BptBALWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [eEthereumNetwork.ropsten]: { @@ -258,6 +262,7 @@ export const CommonsConfig: ICommonConfiguration = { UniWBTCUSDC: ZERO_ADDRESS, UniYFIWETH: ZERO_ADDRESS, BptWBTCWETH: ZERO_ADDRESS, + BptBALWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [eEthereumNetwork.tenderlyMain]: { @@ -280,6 +285,7 @@ export const CommonsConfig: ICommonConfiguration = { UniWBTCUSDC: ZERO_ADDRESS, UniYFIWETH: ZERO_ADDRESS, BptWBTCWETH: ZERO_ADDRESS, + BptBALWETH: ZERO_ADDRESS, USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, }, diff --git a/markets/amm/index.ts b/markets/amm/index.ts index 705e4be3..e42dbdec 100644 --- a/markets/amm/index.ts +++ b/markets/amm/index.ts @@ -22,6 +22,7 @@ import { strategyUSDCWETH, strategyWBTCUSDC, strategyYFIWETH, + strategyBALWETH, } from './reservesConfigs'; // ---------------- @@ -53,6 +54,7 @@ export const AmmConfig: IAmmConfiguration = { UniWBTCUSDC: strategyWBTCUSDC, UniYFIWETH: strategyYFIWETH, BptWBTCWETH: strategyWBTCWETH, + BptBALWETH: strategyBALWETH, }, ReserveAssets: { [eEthereumNetwork.buidlerevm]: {}, @@ -79,6 +81,7 @@ export const AmmConfig: IAmmConfiguration = { UniWBTCUSDC: '0x3d35B5F289f55A580e6F85eE22E6a8f57053b966', UniYFIWETH: '0x5af95ddFACC150a1695A3Fc606459fd0dE57b91f', BptWBTCWETH: '0x110569E3261bC0934dA637b019f6f1b6F50ec574', + BptBALWETH: '0xad01D8e0Fa9EAA8Fe76dA30CFb1BCe12707aE6c5', }, [eEthereumNetwork.ropsten]: { }, @@ -103,6 +106,7 @@ export const AmmConfig: IAmmConfiguration = { UniWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416', UniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', BptWBTCWETH: '0x1efF8aF5D577060BA4ac8A29A13525bb0Ee2A3D5', + BptBALWETH: '0x59A19D8c652FA0284f44113D0ff9aBa70bd46fB4', }, [eEthereumNetwork.tenderlyMain]: { DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F', @@ -125,6 +129,7 @@ export const AmmConfig: IAmmConfiguration = { UniWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416', UniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28', BptWBTCWETH: '0x1efF8aF5D577060BA4ac8A29A13525bb0Ee2A3D5', + BptBALWETH: '0x59A19D8c652FA0284f44113D0ff9aBa70bd46fB4', }, }, }; diff --git a/markets/amm/reservesConfigs.ts b/markets/amm/reservesConfigs.ts index b4143653..79893f4d 100644 --- a/markets/amm/reservesConfigs.ts +++ b/markets/amm/reservesConfigs.ts @@ -232,4 +232,16 @@ export const strategyYFIWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500' -}; \ No newline at end of file +}; + +export const strategyBALWETH: IReserveParams = { + strategy: rateStrategyAmmBase, + baseLTVAsCollateral: '6000', + liquidationThreshold: '6500', + liquidationBonus: '11500', + borrowingEnabled: true, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '1500' +} \ No newline at end of file diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index b157610f..2f0f275b 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -187,6 +187,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, UniYFIWETH: mockTokens.UniYFIWETH.address, BptWBTCWETH: mockTokens.BptWBTCWETH.address, + BptBALWETH: mockTokens.BptBALWETH.address, WMATIC: mockTokens.WMATIC.address, USD: USD_ADDRESS, STAKE: mockTokens.STAKE.address, diff --git a/test-suites/test-amm/__setup.spec.ts b/test-suites/test-amm/__setup.spec.ts index 7d55702e..277998f4 100644 --- a/test-suites/test-amm/__setup.spec.ts +++ b/test-suites/test-amm/__setup.spec.ts @@ -186,6 +186,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { UniWBTCUSDC: mockTokens.UniWBTCUSDC.address, UniYFIWETH: mockTokens.UniYFIWETH.address, BptWBTCWETH: mockTokens.BptWBTCWETH.address, + BptBALWETH: mockTokens.BptBALWETH.address, WMATIC: mockTokens.WMATIC.address, USD: USD_ADDRESS, STAKE: mockTokens.STAKE.address, From 8635e9403bf05aa981479ec0e09ae2f8b1cfb0de Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Fri, 26 Feb 2021 09:41:07 -0500 Subject: [PATCH 163/219] Updated reserve configs and included BptBALWETH --- markets/amm/rateStrategies.ts | 4 ++-- markets/amm/reservesConfigs.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/markets/amm/rateStrategies.ts b/markets/amm/rateStrategies.ts index a4a05300..e6df73ce 100644 --- a/markets/amm/rateStrategies.ts +++ b/markets/amm/rateStrategies.ts @@ -9,8 +9,8 @@ export const rateStrategyAmmBase: IInterestRateStrategyParams = { baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(), variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(), variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(), - stableRateSlope1: '0', - stableRateSlope2: '0', + stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(), + stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(), } // WETH WBTC diff --git a/markets/amm/reservesConfigs.ts b/markets/amm/reservesConfigs.ts index 79893f4d..c92aa42f 100644 --- a/markets/amm/reservesConfigs.ts +++ b/markets/amm/reservesConfigs.ts @@ -135,7 +135,7 @@ export const strategyCRVWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '500' + reserveFactor: '1500' }; export const strategyLINKWETH: IReserveParams = { @@ -237,7 +237,7 @@ export const strategyYFIWETH: IReserveParams = { export const strategyBALWETH: IReserveParams = { strategy: rateStrategyAmmBase, baseLTVAsCollateral: '6000', - liquidationThreshold: '6500', + liquidationThreshold: '7000', liquidationBonus: '11500', borrowingEnabled: true, stableBorrowRateEnabled: false, From 77fab5d3bbe709bee7ba3b69499bed572d7915ab Mon Sep 17 00:00:00 2001 From: The3D Date: Fri, 26 Feb 2021 18:17:10 +0100 Subject: [PATCH 164/219] Added encoded parameter to reserve initialization --- contracts/interfaces/IInitializableAToken.sol | 3 +- .../interfaces/IInitializableDebtToken.sol | 3 +- .../interfaces/ILendingPoolConfigurator.sol | 3 + .../lendingpool/LendingPoolConfigurator.sol | 167 +++++++++--------- contracts/protocol/tokenization/AToken.sol | 3 +- .../protocol/tokenization/StableDebtToken.sol | 3 +- .../tokenization/VariableDebtToken.sol | 3 +- 7 files changed, 98 insertions(+), 87 deletions(-) diff --git a/contracts/interfaces/IInitializableAToken.sol b/contracts/interfaces/IInitializableAToken.sol index 9cffe6ce..599fe6bb 100644 --- a/contracts/interfaces/IInitializableAToken.sol +++ b/contracts/interfaces/IInitializableAToken.sol @@ -27,6 +27,7 @@ interface IInitializableAToken { IAaveIncentivesController incentivesController, uint8 aTokenDecimals, string calldata aTokenName, - string calldata aTokenSymbol + string calldata aTokenSymbol, + bytes calldata params ) external; } diff --git a/contracts/interfaces/IInitializableDebtToken.sol b/contracts/interfaces/IInitializableDebtToken.sol index 0a85c968..e310b108 100644 --- a/contracts/interfaces/IInitializableDebtToken.sol +++ b/contracts/interfaces/IInitializableDebtToken.sol @@ -25,6 +25,7 @@ interface IInitializableDebtToken { IAaveIncentivesController incentivesController, uint8 debtTokenDecimals, string memory debtTokenName, - string memory debtTokenSymbol + string memory debtTokenSymbol, + bytes calldata params ) external; } diff --git a/contracts/interfaces/ILendingPoolConfigurator.sol b/contracts/interfaces/ILendingPoolConfigurator.sol index 8981db6c..7554f2a8 100644 --- a/contracts/interfaces/ILendingPoolConfigurator.sol +++ b/contracts/interfaces/ILendingPoolConfigurator.sol @@ -19,6 +19,7 @@ interface ILendingPoolConfigurator { string variableDebtTokenSymbol; string stableDebtTokenName; string stableDebtTokenSymbol; + bytes params; } struct UpdateATokenInput { @@ -28,6 +29,7 @@ interface ILendingPoolConfigurator { string name; string symbol; address implementation; + bytes params; } struct UpdateDebtTokenInput { @@ -36,6 +38,7 @@ interface ILendingPoolConfigurator { string name; string symbol; address implementation; + bytes params; } /** diff --git a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol index b9811311..49451d92 100644 --- a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol @@ -60,183 +60,186 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur /** * @dev Initializes reserves in batch **/ - function batchInitReserve(InitReserveInput[] calldata inputParams) external onlyPoolAdmin { + function batchInitReserve(InitReserveInput[] calldata input) external onlyPoolAdmin { ILendingPool cachedPool = pool; - for (uint256 i = 0; i < inputParams.length; i++) { - _initReserve(cachedPool, inputParams[i]); + for (uint256 i = 0; i < input.length; i++) { + _initReserve(cachedPool, input[i]); } } - function _initReserve(ILendingPool pool, InitReserveInput calldata inputParams) internal { + function _initReserve(ILendingPool pool, InitReserveInput calldata input) internal { address aTokenProxyAddress = _initTokenWithProxy( - inputParams.aTokenImpl, + input.aTokenImpl, abi.encodeWithSelector( IInitializableAToken.initialize.selector, pool, - inputParams.treasury, - inputParams.underlyingAsset, - IAaveIncentivesController(inputParams.incentivesController), - inputParams.underlyingAssetDecimals, - inputParams.aTokenName, - inputParams.aTokenSymbol + input.treasury, + input.underlyingAsset, + IAaveIncentivesController(input.incentivesController), + input.underlyingAssetDecimals, + input.aTokenName, + input.aTokenSymbol, + input.params ) ); address stableDebtTokenProxyAddress = _initTokenWithProxy( - inputParams.stableDebtTokenImpl, + input.stableDebtTokenImpl, abi.encodeWithSelector( IInitializableDebtToken.initialize.selector, pool, - inputParams.underlyingAsset, - IAaveIncentivesController(inputParams.incentivesController), - inputParams.underlyingAssetDecimals, - inputParams.stableDebtTokenName, - inputParams.stableDebtTokenSymbol + input.underlyingAsset, + IAaveIncentivesController(input.incentivesController), + input.underlyingAssetDecimals, + input.stableDebtTokenName, + input.stableDebtTokenSymbol, + input.params ) ); address variableDebtTokenProxyAddress = _initTokenWithProxy( - inputParams.variableDebtTokenImpl, + input.variableDebtTokenImpl, abi.encodeWithSelector( IInitializableDebtToken.initialize.selector, pool, - inputParams.underlyingAsset, - IAaveIncentivesController(inputParams.incentivesController), - inputParams.underlyingAssetDecimals, - inputParams.variableDebtTokenName, - inputParams.variableDebtTokenSymbol + input.underlyingAsset, + IAaveIncentivesController(input.incentivesController), + input.underlyingAssetDecimals, + input.variableDebtTokenName, + input.variableDebtTokenSymbol, + input.params ) ); pool.initReserve( - inputParams.underlyingAsset, + input.underlyingAsset, aTokenProxyAddress, stableDebtTokenProxyAddress, variableDebtTokenProxyAddress, - inputParams.interestRateStrategyAddress + input.interestRateStrategyAddress ); DataTypes.ReserveConfigurationMap memory currentConfig = - pool.getConfiguration(inputParams.underlyingAsset); + pool.getConfiguration(input.underlyingAsset); - currentConfig.setDecimals(inputParams.underlyingAssetDecimals); + currentConfig.setDecimals(input.underlyingAssetDecimals); currentConfig.setActive(true); currentConfig.setFrozen(false); - pool.setConfiguration(inputParams.underlyingAsset, currentConfig.data); + pool.setConfiguration(input.underlyingAsset, currentConfig.data); emit ReserveInitialized( - inputParams.underlyingAsset, + input.underlyingAsset, aTokenProxyAddress, stableDebtTokenProxyAddress, variableDebtTokenProxyAddress, - inputParams.interestRateStrategyAddress + input.interestRateStrategyAddress ); } /** * @dev Updates the aToken implementation for the reserve **/ - function updateAToken(UpdateATokenInput calldata inputParams) external onlyPoolAdmin { + function updateAToken(UpdateATokenInput calldata input) external onlyPoolAdmin { ILendingPool cachedPool = pool; - DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(inputParams.asset); + DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); - DataTypes.ReserveConfigurationMap memory configuration = - cachedPool.getConfiguration(inputParams.asset); + (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); - (, , , uint256 decimals, ) = configuration.getParamsMemory(); + bytes memory encodedCall = abi.encodeWithSelector( + IInitializableAToken.initialize.selector, + cachedPool, + input.treasury, + input.asset, + input.incentivesController, + decimals, + input.name, + input.symbol, + input.params + ); _upgradeTokenImplementation( reserveData.aTokenAddress, - inputParams.implementation, - abi.encodeWithSelector( - IInitializableAToken.initialize.selector, - cachedPool, - inputParams.treasury, - inputParams.asset, - inputParams.incentivesController, - decimals, - inputParams.name, - inputParams.symbol - ) + input.implementation, + encodedCall ); - emit ATokenUpgraded(inputParams.asset, reserveData.aTokenAddress, inputParams.implementation); + emit ATokenUpgraded(input.asset, reserveData.aTokenAddress, input.implementation); } /** * @dev Updates the stable debt token implementation for the reserve **/ - function updateStableDebtToken(UpdateDebtTokenInput calldata inputParams) external onlyPoolAdmin { + function updateStableDebtToken(UpdateDebtTokenInput calldata input) external onlyPoolAdmin { ILendingPool cachedPool = pool; - DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(inputParams.asset); + DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); + + (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); - DataTypes.ReserveConfigurationMap memory configuration = - cachedPool.getConfiguration(inputParams.asset); - - (, , , uint256 decimals, ) = configuration.getParamsMemory(); + bytes memory encodedCall = abi.encodeWithSelector( + IInitializableDebtToken.initialize.selector, + cachedPool, + input.asset, + input.incentivesController, + decimals, + input.name, + input.symbol, + input.params + ); _upgradeTokenImplementation( reserveData.stableDebtTokenAddress, - inputParams.implementation, - abi.encodeWithSelector( - IInitializableDebtToken.initialize.selector, - cachedPool, - inputParams.asset, - inputParams.incentivesController, - decimals, - inputParams.name, - inputParams.symbol - ) + input.implementation, + encodedCall ); emit StableDebtTokenUpgraded( - inputParams.asset, + input.asset, reserveData.stableDebtTokenAddress, - inputParams.implementation + input.implementation ); } /** * @dev Updates the variable debt token implementation for the asset **/ - function updateVariableDebtToken(UpdateDebtTokenInput calldata inputParams) + function updateVariableDebtToken(UpdateDebtTokenInput calldata input) external onlyPoolAdmin { ILendingPool cachedPool = pool; - DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(inputParams.asset); + DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); - DataTypes.ReserveConfigurationMap memory configuration = - cachedPool.getConfiguration(inputParams.asset); + (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); - (, , , uint256 decimals, ) = configuration.getParamsMemory(); + bytes memory encodedCall = abi.encodeWithSelector( + IInitializableDebtToken.initialize.selector, + cachedPool, + input.asset, + input.incentivesController, + decimals, + input.name, + input.symbol, + input.params + ); _upgradeTokenImplementation( reserveData.variableDebtTokenAddress, - inputParams.implementation, - abi.encodeWithSelector( - IInitializableDebtToken.initialize.selector, - cachedPool, - inputParams.asset, - inputParams.incentivesController, - decimals, - inputParams.name, - inputParams.symbol - ) + input.implementation, + encodedCall ); emit VariableDebtTokenUpgraded( - inputParams.asset, + input.asset, reserveData.variableDebtTokenAddress, - inputParams.implementation + input.implementation ); } diff --git a/contracts/protocol/tokenization/AToken.sol b/contracts/protocol/tokenization/AToken.sol index 1a47ebf4..f1cfc33a 100644 --- a/contracts/protocol/tokenization/AToken.sol +++ b/contracts/protocol/tokenization/AToken.sol @@ -68,7 +68,8 @@ contract AToken is IAaveIncentivesController incentivesController, uint8 aTokenDecimals, string calldata aTokenName, - string calldata aTokenSymbol + string calldata aTokenSymbol, + bytes calldata params ) external override initializer { uint256 chainId; diff --git a/contracts/protocol/tokenization/StableDebtToken.sol b/contracts/protocol/tokenization/StableDebtToken.sol index f52c4931..3f8a5bfd 100644 --- a/contracts/protocol/tokenization/StableDebtToken.sol +++ b/contracts/protocol/tokenization/StableDebtToken.sol @@ -44,7 +44,8 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { IAaveIncentivesController incentivesController, uint8 debtTokenDecimals, string memory debtTokenName, - string memory debtTokenSymbol + string memory debtTokenSymbol, + bytes calldata params ) public override initializer { _setName(debtTokenName); _setSymbol(debtTokenSymbol); diff --git a/contracts/protocol/tokenization/VariableDebtToken.sol b/contracts/protocol/tokenization/VariableDebtToken.sol index 60a47e12..157c703a 100644 --- a/contracts/protocol/tokenization/VariableDebtToken.sol +++ b/contracts/protocol/tokenization/VariableDebtToken.sol @@ -38,7 +38,8 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { IAaveIncentivesController incentivesController, uint8 debtTokenDecimals, string memory debtTokenName, - string memory debtTokenSymbol + string memory debtTokenSymbol, + bytes calldata params ) public override initializer { _setName(debtTokenName); _setSymbol(debtTokenSymbol); From 682a7d13fec9ee9f3e50412d68d7b00664a3b252 Mon Sep 17 00:00:00 2001 From: The3D Date: Fri, 26 Feb 2021 19:18:38 +0100 Subject: [PATCH 165/219] Updated tests --- helpers/contracts-deployments.ts | 15 ++++++++------- helpers/init-helpers.ts | 4 ++++ test-suites/test-aave/upgradeability.spec.ts | 15 +++++++++++++++ test-suites/test-amm/upgradeability.spec.ts | 5 +++++ 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 84e12764..4fe188de 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -411,7 +411,8 @@ export const deployDelegationAwareAToken = async ( incentivesController, '18', name, - symbol + symbol, + '0x10' ); return instance; @@ -504,7 +505,7 @@ export const authorizeWETHGateway = async ( .authorizeLendingPool(lendingPool); export const deployMockStableDebtToken = async ( - args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], + args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string, string], verify?: boolean ) => { const instance = await withSaveAndVerify( @@ -514,7 +515,7 @@ export const deployMockStableDebtToken = async ( verify ); - await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4]); + await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4], args[5]); return instance; }; @@ -528,7 +529,7 @@ export const deployWETHMocked = async (verify?: boolean) => ); export const deployMockVariableDebtToken = async ( - args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], + args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string, string], verify?: boolean ) => { const instance = await withSaveAndVerify( @@ -538,13 +539,13 @@ export const deployMockVariableDebtToken = async ( verify ); - await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4]); + await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4], args[5]); return instance; }; export const deployMockAToken = async ( - args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string], + args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string, string], verify?: boolean ) => { const instance = await withSaveAndVerify( @@ -554,7 +555,7 @@ export const deployMockAToken = async ( verify ); - await instance.initialize(args[0], args[2], args[1], args[3], '18', args[4], args[5]); + await instance.initialize(args[0], args[2], args[1], args[3], '18', args[4], args[5], args[6]); return instance; }; diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 7d8f7eb4..eb483420 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -85,6 +85,7 @@ export const initReservesByHelper = async ( variableDebtTokenSymbol: string; stableDebtTokenName: string; stableDebtTokenSymbol: string; + params: string; }[] = []; let strategyRates: [ @@ -208,6 +209,7 @@ export const initReservesByHelper = async ( variableDebtTokenSymbol: `variableDebt${symbolPrefix}${reserveSymbols[i]}`, stableDebtTokenName: `${stableDebtTokenNamePrefix} ${reserveSymbols[i]}`, stableDebtTokenSymbol: `stableDebt${symbolPrefix}${reserveSymbols[i]}`, + params: '0x10' }); } @@ -416,6 +418,7 @@ export const initTokenReservesByHelper = async ( variableDebtTokenSymbol: string; stableDebtTokenName: string; stableDebtTokenSymbol: string; + params: string; }[] = []; const network = @@ -554,6 +557,7 @@ export const initTokenReservesByHelper = async ( variableDebtTokenSymbol: `variableDebt${reserveSymbols[i]}`, stableDebtTokenName: `Aave stable debt bearing ${reserveSymbols[i]}`, stableDebtTokenSymbol: `stableDebt${reserveSymbols[i]}`, + params: '0x10' }); } diff --git a/test-suites/test-aave/upgradeability.spec.ts b/test-suites/test-aave/upgradeability.spec.ts index 74e02325..8e27a350 100644 --- a/test-suites/test-aave/upgradeability.spec.ts +++ b/test-suites/test-aave/upgradeability.spec.ts @@ -34,6 +34,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { ZERO_ADDRESS, 'Aave Interest bearing DAI updated', 'aDAI', + '0x10' ]); const stableDebtTokenInstance = await deployMockStableDebtToken([ @@ -42,6 +43,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { ZERO_ADDRESS, 'Aave stable debt bearing DAI updated', 'stableDebtDAI', + '0x10' ]); const variableDebtTokenInstance = await deployMockVariableDebtToken([ @@ -50,6 +52,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { ZERO_ADDRESS, 'Aave variable debt bearing DAI updated', 'variableDebtDAI', + '0x10' ]); newATokenAddress = aTokenInstance.address; @@ -70,6 +73,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { name: string; symbol: string; implementation: string; + params: string } = { asset: dai.address, treasury: ZERO_ADDRESS, @@ -77,6 +81,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { name: name, symbol: symbol, implementation: newATokenAddress, + params: "0x10" }; await expect( configurator.connect(users[1].signer).updateAToken(updateATokenInputParams) @@ -96,6 +101,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { name: string; symbol: string; implementation: string; + params: string } = { asset: dai.address, treasury: ZERO_ADDRESS, @@ -103,6 +109,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { name: name, symbol: symbol, implementation: newATokenAddress, + params: "0x10" }; await configurator.updateAToken(updateATokenInputParams); @@ -124,12 +131,14 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { name: string; symbol: string; implementation: string; + params: string; } = { asset: dai.address, incentivesController: ZERO_ADDRESS, name: name, symbol: symbol, implementation: newStableTokenAddress, + params: '0x10' } await expect( @@ -152,12 +161,14 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { name: string; symbol: string; implementation: string; + params: string; } = { asset: dai.address, incentivesController: ZERO_ADDRESS, name: name, symbol: symbol, implementation: newStableTokenAddress, + params: '0x10' } await configurator.updateStableDebtToken(updateDebtTokenInput); @@ -183,12 +194,14 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { name: string; symbol: string; implementation: string; + params: string; } = { asset: dai.address, incentivesController: ZERO_ADDRESS, name: name, symbol: symbol, implementation: newVariableTokenAddress, + params: '0x10' } await expect( @@ -210,12 +223,14 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { name: string; symbol: string; implementation: string; + params: string; } = { asset: dai.address, incentivesController: ZERO_ADDRESS, name: name, symbol: symbol, implementation: newVariableTokenAddress, + params: '0x10' } //const name = await (await getAToken(newATokenAddress)).name(); diff --git a/test-suites/test-amm/upgradeability.spec.ts b/test-suites/test-amm/upgradeability.spec.ts index bbe5799b..89626b41 100644 --- a/test-suites/test-amm/upgradeability.spec.ts +++ b/test-suites/test-amm/upgradeability.spec.ts @@ -34,6 +34,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { ZERO_ADDRESS, 'Aave AMM Market DAI updated', 'aAmmDAI', + '0x10' ]); const stableDebtTokenInstance = await deployMockStableDebtToken([ @@ -42,6 +43,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { ZERO_ADDRESS, 'Aave AMM Market stable debt DAI updated', 'stableDebtAmmDAI', + '0x10' ]); const variableDebtTokenInstance = await deployMockVariableDebtToken([ @@ -50,6 +52,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { ZERO_ADDRESS, 'Aave AMM Market variable debt DAI updated', 'variableDebtAmmDAI', + '0x10' ]); newATokenAddress = aTokenInstance.address; @@ -70,6 +73,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { name: string; symbol: string; implementation: string; + params: string; } = { asset: dai.address, treasury: ZERO_ADDRESS, @@ -77,6 +81,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { name: name, symbol: symbol, implementation: newATokenAddress, + params: '0x10' }; await expect( configurator.connect(users[1].signer).updateAToken(updateATokenInputParams) From 03a410230dc96a2e28841e9851e929552922269f Mon Sep 17 00:00:00 2001 From: The3D Date: Mon, 1 Mar 2021 15:58:31 +0100 Subject: [PATCH 166/219] Updated interest rate strategy to generalize fetching of the available liquidity --- .../interfaces/IReserveInterestRateStrategy.sol | 4 +++- .../DefaultReserveInterestRateStrategy.sol | 13 ++++++++++--- contracts/protocol/libraries/logic/ReserveLogic.sol | 6 +++--- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/contracts/interfaces/IReserveInterestRateStrategy.sol b/contracts/interfaces/IReserveInterestRateStrategy.sol index 430145e3..70eb99ee 100644 --- a/contracts/interfaces/IReserveInterestRateStrategy.sol +++ b/contracts/interfaces/IReserveInterestRateStrategy.sol @@ -13,7 +13,9 @@ interface IReserveInterestRateStrategy { function calculateInterestRates( address reserve, - uint256 utilizationRate, + address aToken, + uint256 liquidityAdded, + uint256 liquidityTaken, uint256 totalStableDebt, uint256 totalVariableDebt, uint256 averageStableBorrowRate, diff --git a/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol b/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol index c2584a22..da8cdaef 100644 --- a/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol +++ b/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol @@ -7,6 +7,7 @@ import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {PercentageMath} from '../libraries/math/PercentageMath.sol'; import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; import {ILendingRateOracle} from '../../interfaces/ILendingRateOracle.sol'; +import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol'; /** * @title DefaultReserveInterestRateStrategy contract @@ -102,12 +103,14 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { uint256 currentStableBorrowRate; uint256 currentLiquidityRate; uint256 utilizationRate; + uint256 availableLiquidity; } /** * @dev Calculates the interest rates depending on the reserve's state and configurations * @param reserve The address of the reserve - * @param availableLiquidity The liquidity available in the reserve + * @param liquidityAdded The liquidity added during the operation + * @param liquidityTaken The liquidity taken during the operation * @param totalStableDebt The total borrowed from the reserve a stable rate * @param totalVariableDebt The total borrowed from the reserve at a variable rate * @param averageStableBorrowRate The weighted average of all the stable rate loans @@ -116,7 +119,9 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { **/ function calculateInterestRates( address reserve, - uint256 availableLiquidity, + address aToken, + uint256 liquidityAdded, + uint256 liquidityTaken, uint256 totalStableDebt, uint256 totalVariableDebt, uint256 averageStableBorrowRate, @@ -137,9 +142,11 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { vars.currentVariableBorrowRate = 0; vars.currentStableBorrowRate = 0; vars.currentLiquidityRate = 0; + vars.availableLiquidity = IERC20(reserve).balanceOf(aToken); + vars.availableLiquidity = vars.availableLiquidity.add(liquidityAdded).sub(liquidityTaken); uint256 utilizationRate = - vars.totalDebt == 0 ? 0 : vars.totalDebt.rayDiv(availableLiquidity.add(vars.totalDebt)); + vars.totalDebt == 0 ? 0 : vars.totalDebt.rayDiv(vars.availableLiquidity.add(vars.totalDebt)); vars.currentStableBorrowRate = ILendingRateOracle(addressesProvider.getLendingRateOracle()) .getMarketBorrowRate(reserve); diff --git a/contracts/protocol/libraries/logic/ReserveLogic.sol b/contracts/protocol/libraries/logic/ReserveLogic.sol index 3b0884c2..2b5b2cf4 100644 --- a/contracts/protocol/libraries/logic/ReserveLogic.sol +++ b/contracts/protocol/libraries/logic/ReserveLogic.sol @@ -216,15 +216,15 @@ library ReserveLogic { .scaledTotalSupply() .rayMul(reserve.variableBorrowIndex); - vars.availableLiquidity = IERC20(reserveAddress).balanceOf(aTokenAddress); - ( vars.newLiquidityRate, vars.newStableRate, vars.newVariableRate ) = IReserveInterestRateStrategy(reserve.interestRateStrategyAddress).calculateInterestRates( reserveAddress, - vars.availableLiquidity.add(liquidityAdded).sub(liquidityTaken), + aTokenAddress, + liquidityAdded, + liquidityTaken, vars.totalStableDebt, vars.totalVariableDebt, vars.avgStableRate, From bc1a237f340dbaf713dedf413c3108bc28b6b8ec Mon Sep 17 00:00:00 2001 From: The3D Date: Mon, 1 Mar 2021 17:47:27 +0100 Subject: [PATCH 167/219] Added handleRepayment() function --- contracts/interfaces/IAToken.sol | 9 ++++++++- contracts/protocol/lendingpool/LendingPool.sol | 2 ++ contracts/protocol/tokenization/AToken.sol | 7 +++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/contracts/interfaces/IAToken.sol b/contracts/interfaces/IAToken.sol index ca338270..3a6ac663 100644 --- a/contracts/interfaces/IAToken.sol +++ b/contracts/interfaces/IAToken.sol @@ -82,12 +82,19 @@ interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken { /** * @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer * assets in borrow(), withdraw() and flashLoan() - * @param user The recipient of the aTokens + * @param user The recipient of the underlying * @param amount The amount getting transferred * @return The amount transferred **/ function transferUnderlyingTo(address user, uint256 amount) external returns (uint256); + /** + * @dev Invoked to execute actions on the aToken side after a repayment. + * @param user The user executing the repayment + * @param amount The amount getting repaid + **/ + function handleRepayment(address user, uint256 amount) external; + /** * @dev Returns the address of the incentives controller contract **/ diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 79bb93aa..8e38650c 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -282,6 +282,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage IERC20(asset).safeTransferFrom(msg.sender, aToken, paybackAmount); + IAToken(aToken).handleRepayment(msg.sender, paybackAmount); + emit Repay(asset, onBehalfOf, msg.sender, paybackAmount); return paybackAmount; diff --git a/contracts/protocol/tokenization/AToken.sol b/contracts/protocol/tokenization/AToken.sol index f1cfc33a..cfb45621 100644 --- a/contracts/protocol/tokenization/AToken.sol +++ b/contracts/protocol/tokenization/AToken.sol @@ -304,6 +304,13 @@ contract AToken is return amount; } + /** + * @dev Invoked to execute actions on the aToken side after a repayment. + * @param user The user executing the repayment + * @param amount The amount getting repaid + **/ + function handleRepayment(address user, uint256 amount) external override onlyLendingPool {} + /** * @dev implements the permit function as for * https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md From 03dc5370ee22739d44173c72f116db270e3c85f4 Mon Sep 17 00:00:00 2001 From: The3D Date: Mon, 1 Mar 2021 18:33:48 +0100 Subject: [PATCH 168/219] Added initialized events --- contracts/interfaces/IInitializableAToken.sol | 22 +++++++++++++++++++ .../interfaces/IInitializableDebtToken.sol | 20 +++++++++++++++++ contracts/protocol/tokenization/AToken.sol | 11 ++++++++++ .../protocol/tokenization/StableDebtToken.sol | 10 +++++++++ .../tokenization/VariableDebtToken.sol | 10 +++++++++ 5 files changed, 73 insertions(+) diff --git a/contracts/interfaces/IInitializableAToken.sol b/contracts/interfaces/IInitializableAToken.sol index 599fe6bb..5038580a 100644 --- a/contracts/interfaces/IInitializableAToken.sol +++ b/contracts/interfaces/IInitializableAToken.sol @@ -10,6 +10,28 @@ import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; * @author Aave **/ interface IInitializableAToken { + /** + * @dev Emitted when an aToken is initialized + * @param underlyingAsset The address of the underlying asset + * @param pool The address of the associated lending pool + * @param treasury The address of the treasury + * @param incentivesController The address of the incentives controller for this aToken + * @param aTokenDecimals the decimals of the underlying + * @param aTokenName the name of the aToken + * @param aTokenSymbol the symbol of the aToken + * @param params A set of encoded parameters for additional initialization + **/ + event Initialized( + address indexed underlyingAsset, + address indexed pool, + address treasury, + address incentivesController, + uint8 aTokenDecimals, + string aTokenName, + string aTokenSymbol, + bytes params + ); + /** * @dev Initializes the aToken * @param pool The address of the lending pool where this aToken will be used diff --git a/contracts/interfaces/IInitializableDebtToken.sol b/contracts/interfaces/IInitializableDebtToken.sol index e310b108..c5bdb3f5 100644 --- a/contracts/interfaces/IInitializableDebtToken.sol +++ b/contracts/interfaces/IInitializableDebtToken.sol @@ -10,6 +10,26 @@ import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; * @author Aave **/ interface IInitializableDebtToken { + /** + * @dev Emitted when a debt token is initialized + * @param underlyingAsset The address of the underlying asset + * @param pool The address of the associated lending pool + * @param incentivesController The address of the incentives controller for this aToken + * @param debtTokenDecimals the decimals of the debt token + * @param debtTokenName the name of the debt token + * @param debtTokenSymbol the symbol of the debt token + * @param params A set of encoded parameters for additional initialization + **/ + event Initialized( + address indexed underlyingAsset, + address indexed pool, + address incentivesController, + uint8 debtTokenDecimals, + string debtTokenName, + string debtTokenSymbol, + bytes params + ); + /** * @dev Initializes the debt token. * @param pool The address of the lending pool where this aToken will be used diff --git a/contracts/protocol/tokenization/AToken.sol b/contracts/protocol/tokenization/AToken.sol index cfb45621..f2784732 100644 --- a/contracts/protocol/tokenization/AToken.sol +++ b/contracts/protocol/tokenization/AToken.sol @@ -96,6 +96,17 @@ contract AToken is _treasury = treasury; _underlyingAsset = underlyingAsset; _incentivesController = incentivesController; + + emit Initialized( + underlyingAsset, + address(pool), + treasury, + address(incentivesController), + aTokenDecimals, + aTokenName, + aTokenSymbol, + params + ); } /** diff --git a/contracts/protocol/tokenization/StableDebtToken.sol b/contracts/protocol/tokenization/StableDebtToken.sol index 3f8a5bfd..2212e9cf 100644 --- a/contracts/protocol/tokenization/StableDebtToken.sol +++ b/contracts/protocol/tokenization/StableDebtToken.sol @@ -54,6 +54,16 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { _pool = pool; _underlyingAsset = underlyingAsset; _incentivesController = incentivesController; + + emit Initialized( + underlyingAsset, + address(pool), + address(incentivesController), + debtTokenDecimals, + debtTokenName, + debtTokenSymbol, + params + ); } /** diff --git a/contracts/protocol/tokenization/VariableDebtToken.sol b/contracts/protocol/tokenization/VariableDebtToken.sol index 157c703a..a7a28176 100644 --- a/contracts/protocol/tokenization/VariableDebtToken.sol +++ b/contracts/protocol/tokenization/VariableDebtToken.sol @@ -48,6 +48,16 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { _pool = pool; _underlyingAsset = underlyingAsset; _incentivesController = incentivesController; + + emit Initialized( + underlyingAsset, + address(pool), + address(incentivesController), + debtTokenDecimals, + debtTokenName, + debtTokenSymbol, + params + ); } /** From eb9077f25ec7b937f27edc37c422ad79ad69a1a7 Mon Sep 17 00:00:00 2001 From: The3D Date: Mon, 1 Mar 2021 20:26:08 +0100 Subject: [PATCH 169/219] Refactored interest rate strategies tests --- .../DefaultReserveInterestRateStrategy.sol | 13 +- helpers/contracts-deployments.ts | 7 +- test-suites/test-aave/pool-modifiers.spec.ts | 241 -------------- test-suites/test-aave/rate-strategy.spec.ts | 308 ++++++++++-------- test-suites/test-amm/rate-strategy.spec.ts | 165 ---------- 5 files changed, 179 insertions(+), 555 deletions(-) delete mode 100644 test-suites/test-aave/pool-modifiers.spec.ts delete mode 100644 test-suites/test-amm/rate-strategy.spec.ts diff --git a/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol b/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol index da8cdaef..2863a3cb 100644 --- a/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol +++ b/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol @@ -8,6 +8,7 @@ import {PercentageMath} from '../libraries/math/PercentageMath.sol'; import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; import {ILendingRateOracle} from '../../interfaces/ILendingRateOracle.sol'; import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol'; +import 'hardhat/console.sol'; /** * @title DefaultReserveInterestRateStrategy contract @@ -145,15 +146,15 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { vars.availableLiquidity = IERC20(reserve).balanceOf(aToken); vars.availableLiquidity = vars.availableLiquidity.add(liquidityAdded).sub(liquidityTaken); - uint256 utilizationRate = + vars.utilizationRate = vars.totalDebt == 0 ? 0 : vars.totalDebt.rayDiv(vars.availableLiquidity.add(vars.totalDebt)); vars.currentStableBorrowRate = ILendingRateOracle(addressesProvider.getLendingRateOracle()) .getMarketBorrowRate(reserve); - if (utilizationRate > OPTIMAL_UTILIZATION_RATE) { + if (vars.utilizationRate > OPTIMAL_UTILIZATION_RATE) { uint256 excessUtilizationRateRatio = - utilizationRate.sub(OPTIMAL_UTILIZATION_RATE).rayDiv(EXCESS_UTILIZATION_RATE); + vars.utilizationRate.sub(OPTIMAL_UTILIZATION_RATE).rayDiv(EXCESS_UTILIZATION_RATE); vars.currentStableBorrowRate = vars.currentStableBorrowRate.add(_stableRateSlope1).add( _stableRateSlope2.rayMul(excessUtilizationRateRatio) @@ -164,10 +165,10 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { ); } else { vars.currentStableBorrowRate = vars.currentStableBorrowRate.add( - _stableRateSlope1.rayMul(utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE)) + _stableRateSlope1.rayMul(vars.utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE)) ); vars.currentVariableBorrowRate = _baseVariableBorrowRate.add( - utilizationRate.rayMul(_variableRateSlope1).rayDiv(OPTIMAL_UTILIZATION_RATE) + vars.utilizationRate.rayMul(_variableRateSlope1).rayDiv(OPTIMAL_UTILIZATION_RATE) ); } @@ -178,7 +179,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { .currentVariableBorrowRate, averageStableBorrowRate ) - .rayMul(utilizationRate) + .rayMul(vars.utilizationRate) .percentMul(PercentageMath.PERCENTAGE_FACTOR.sub(reserveFactor)); return ( diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 4fe188de..07f34a91 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -310,7 +310,7 @@ export const deployStableDebtToken = async ( verify ); - await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4]); + await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4], '0x10'); return instance; }; @@ -326,7 +326,7 @@ export const deployVariableDebtToken = async ( verify ); - await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4]); + await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4], '0x10'); return instance; }; @@ -372,7 +372,8 @@ export const deployGenericAToken = async ( incentivesController, '18', name, - symbol + symbol, + '0x10' ); return instance; diff --git a/test-suites/test-aave/pool-modifiers.spec.ts b/test-suites/test-aave/pool-modifiers.spec.ts deleted file mode 100644 index fb915b15..00000000 --- a/test-suites/test-aave/pool-modifiers.spec.ts +++ /dev/null @@ -1,241 +0,0 @@ -// import {iATokenBase, iAssetsWithoutETH, ITestEnvWithoutInstances, RateMode} from '../utils/types'; -// import { -// LendingPoolConfiguratorInstance, -// LendingPoolInstance, -// ATokenInstance, -// LendingPoolCoreInstance, -// MintableERC20Instance, -// } from '../utils/typechain-types/truffle-contracts'; -// import {testEnvProviderWithoutInstances} from '../utils/truffle/dlp-tests-env'; -// import {oneEther, ETHEREUM_ADDRESS} from '../utils/constants'; -// import {convertToCurrencyDecimals} from '../utils/misc-utils'; - -// const expectRevert = require('@openzeppelin/test-helpers').expectRevert; - -// contract('LendingPool: Modifiers', async ([deployer, ...users]) => { -// let _testEnvProvider: ITestEnvWithoutInstances; -// let _lendingPoolConfiguratorInstance: LendingPoolConfiguratorInstance; -// let _lendingPoolInstance: LendingPoolInstance; -// let _lendingPoolCoreInstance: LendingPoolCoreInstance; -// let _aTokenInstances: iATokenBase; -// let _tokenInstances: iAssetsWithoutETH; - -// before('Initializing LendingPool test variables', async () => { -// console.time('setup-test'); -// _testEnvProvider = await testEnvProviderWithoutInstances(artifacts, [deployer, ...users]); - -// const { -// getAllAssetsInstances, -// getLendingPoolInstance, -// getLendingPoolCoreInstance, -// getLendingPoolConfiguratorInstance, -// getATokenInstances, -// } = _testEnvProvider; -// const instances = await Promise.all([ -// getLendingPoolInstance(), -// getLendingPoolCoreInstance(), -// getLendingPoolConfiguratorInstance(), -// getATokenInstances(), -// getAllAssetsInstances(), -// ]); - -// _lendingPoolInstance = instances[0]; -// _lendingPoolCoreInstance = instances[1]; -// _lendingPoolConfiguratorInstance = instances[2]; - -// _aTokenInstances = instances[3]; -// _tokenInstances = instances[4]; -// console.timeEnd('setup-test'); -// }); - -// it('Tries to deposit in an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.deposit(deployer, '1', '0'), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to invoke redeemUnderlying on an reserve, from a non-aToken address', async () => { -// await expectRevert( -// _lendingPoolInstance.redeemUnderlying(ETHEREUM_ADDRESS, deployer, '1', '0'), -// 'The caller of this function can only be the aToken contract of this reserve' -// ); -// }); - -// it('Tries to borrow from an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.borrow(deployer, '1', '0', RateMode.Stable), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to repay in an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.repay(deployer, '1', deployer), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to swapBorrowRateMode on an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.swapBorrowRateMode(deployer), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to rebalanceStableBorrowRate on an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.rebalanceStableBorrowRate(deployer, deployer), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to setUserUseReserveAsCollateral on an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.setUserUseReserveAsCollateral(deployer, true), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to invoke liquidationCall on an inactive reserve', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.liquidationCall(ETHEREUM_ADDRESS, deployer, deployer, '1', false), -// 'Action requires an active reserve' -// ); -// }); - -// it('Tries to invoke liquidationCall on an inactive collateral', async () => { -// //using the deployer address as a fake reserve address -// await expectRevert( -// _lendingPoolInstance.liquidationCall(deployer, ETHEREUM_ADDRESS, deployer, '1', false), -// 'Action requires an active reserve' -// ); -// }); - -// it('Freezes the ETH reserve', async () => { -// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS); -// }); - -// it('tries to deposit in a freezed reserve', async () => { -// await expectRevert( -// _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, '1', '0'), -// 'Action requires an unfreezed reserve' -// ); -// }); - -// it('tries to borrow from a freezed reserve', async () => { -// await expectRevert( -// _lendingPoolInstance.borrow(ETHEREUM_ADDRESS, '1', '0', '0'), -// 'Action requires an unfreezed reserve' -// ); -// }); - -// it('tries to swap interest rate mode in a freezed reserve', async () => { -// await expectRevert( -// _lendingPoolInstance.swapBorrowRateMode(ETHEREUM_ADDRESS), -// 'Action requires an unfreezed reserve' -// ); -// }); - -// it('tries to disable as collateral a freezed reserve', async () => { -// await expectRevert( -// _lendingPoolInstance.setUserUseReserveAsCollateral(ETHEREUM_ADDRESS, false), -// 'Action requires an unfreezed reserve' -// ); -// }); - -// it('unfreezes the reserve, user deposits 1 ETH, freezes the reserve, check that the user can redeem', async () => { -// const {aWETH} = _aTokenInstances; - -// //unfreezes the reserve -// await _lendingPoolConfiguratorInstance.unfreezeReserve(ETHEREUM_ADDRESS); - -// //deposit 1 ETH -// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, oneEther, '0', { -// value: oneEther.toString(), -// }); - -// //freezes the reserve -// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS); - -// const balance = await aWETH.balanceOf(deployer); - -// await aWETH.redeem(balance); -// }); - -// it('unfreezes the reserve, user 0 deposits 100 DAI, user 1 deposits 1 ETH and borrows 50 DAI, freezes the reserve, checks that the user 1 can repay', async () => { -// const {aWETH, aDAI} = _aTokenInstances; -// const {DAI} = _tokenInstances; - -// //unfreezes the reserve -// await _lendingPoolConfiguratorInstance.unfreezeReserve(ETHEREUM_ADDRESS); - -// const amountDAI = await convertToCurrencyDecimals(DAI.address, '100'); - -// //user 0 deposits 100 DAI -// await DAI.mint(amountDAI, {from: users[0]}); - -// await DAI.approve(_lendingPoolCoreInstance.address, amountDAI, {from: users[0]}); - -// await _lendingPoolInstance.deposit(DAI.address, amountDAI, '0', {from: users[0]}); - -// //user 1 deposits 1 ETH -// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, oneEther, '0', { -// from: users[1], -// value: oneEther.toString(), -// }); - -// const amountDAIToBorrow = await convertToCurrencyDecimals(DAI.address, '10'); - -// //user 1 borrows 10 DAI -// await _lendingPoolInstance.borrow(DAI.address, amountDAIToBorrow, RateMode.Stable, '0', { -// from: users[1], -// }); - -// //freezes the reserve -// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS); - -// //user 1 repays 1 DAI -// await DAI.approve(_lendingPoolCoreInstance.address, amountDAIToBorrow, {from: users[1]}); - -// await _lendingPoolInstance.repay(DAI.address, oneEther, users[1], {from: users[1]}); -// }); - -// it('Check that liquidationCall can be executed on a freezed reserve', async () => { -// const {aWETH, aDAI} = _aTokenInstances; -// const {DAI} = _tokenInstances; - -// //user 2 tries to liquidate - -// await expectRevert( -// _lendingPoolInstance.liquidationCall( -// ETHEREUM_ADDRESS, -// DAI.address, -// users[1], -// oneEther, -// true, -// {from: users[2]} -// ), -// 'Health factor is not below the threshold' -// ); -// }); - -// it('Check that rebalanceStableBorrowRate can be executed on a freezed reserve', async () => { -// const {aWETH, aDAI} = _aTokenInstances; -// const {DAI} = _tokenInstances; - -// //user 2 tries to liquidate - -// await expectRevert( -// _lendingPoolInstance.rebalanceStableBorrowRate(DAI.address, users[1]), -// 'Interest rate rebalance conditions were not met' -// ); -// }); -// }); diff --git a/test-suites/test-aave/rate-strategy.spec.ts b/test-suites/test-aave/rate-strategy.spec.ts index b56c754e..83021e97 100644 --- a/test-suites/test-aave/rate-strategy.spec.ts +++ b/test-suites/test-aave/rate-strategy.spec.ts @@ -1,165 +1,193 @@ -// import { -// IReserveParams, -// iAavePoolAssets, -// iAssetsWithoutETH, -// ITestEnvWithoutInstances, -// } from "../utils/types" -// import { +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { deployDefaultReserveInterestRateStrategy } from '../../helpers/contracts-deployments'; -// LendingPoolAddressesProviderInstance, +import { APPROVAL_AMOUNT_LENDING_POOL, PERCENTAGE_FACTOR, RAY } from '../../helpers/constants'; -// DefaultReserveInterestRateStrategyInstance, -// MintableERC20Instance, -// } from "../utils/typechain-types/truffle-contracts" -// import { testEnvProviderWithoutInstances} from "../utils/truffle/dlp-tests-env" -// import {RAY} from "../utils/constants" -// import BigNumber from "bignumber.js" +import { rateStrategyStableOne } from '../../markets/aave/rateStrategies'; -// const {expect} = require("chai") +import { strategyDAI } from '../../markets/aave/reservesConfigs'; +import { AToken, DefaultReserveInterestRateStrategy, MintableERC20 } from '../../types'; +import BigNumber from 'bignumber.js'; +import './helpers/utils/math'; -// contract("Interest rate strategy", async ([deployer, ...users]) => { -// let _testEnvProvider: ITestEnvWithoutInstances -// let _strategyInstance: DefaultReserveInterestRateStrategyInstance -// let _tokenInstances: iAssetsWithoutETH -// let _addressesProviderInstance: LendingPoolAddressesProviderInstance -// let _reservesParams: iAavePoolAssets +const { expect } = require('chai'); -// before("Initializing test variables", async () => { -// console.time('setup-test'); -// _testEnvProvider = await testEnvProviderWithoutInstances( -// artifacts, -// [deployer, ...users], -// ) +makeSuite('Interest rate strategy tests', (testEnv: TestEnv) => { + let strategyInstance: DefaultReserveInterestRateStrategy; + let dai: MintableERC20; + let aDai: AToken; -// const { -// getAllAssetsInstances, -// getLendingPoolAddressesProviderInstance, -// getAavePoolReservesParams, -// } = _testEnvProvider + before(async () => { + dai = testEnv.dai; + aDai = testEnv.aDai; -// const instances = await Promise.all([ -// getAllAssetsInstances(), -// getLendingPoolAddressesProviderInstance() -// ]) + const { addressesProvider } = testEnv; -// _tokenInstances = instances[0] -// _addressesProviderInstance = instances[1] -// _reservesParams = await getAavePoolReservesParams() -// console.timeEnd('setup-test'); -// }) + strategyInstance = await deployDefaultReserveInterestRateStrategy( + [ + addressesProvider.address, + rateStrategyStableOne.optimalUtilizationRate, + rateStrategyStableOne.baseVariableBorrowRate, + rateStrategyStableOne.variableRateSlope1, + rateStrategyStableOne.variableRateSlope2, + rateStrategyStableOne.stableRateSlope1, + rateStrategyStableOne.stableRateSlope2, + ], + false + ); + }); -// it("Deploys a new instance of a DefaultReserveInterestRateStrategy contract", async () => { -// const {DAI: daiInstance} = _tokenInstances + it('Checks rates at 0% utilization rate, empty reserve', async () => { + const { + 0: currentLiquidityRate, + 1: currentStableBorrowRate, + 2: currentVariableBorrowRate, + } = await strategyInstance.calculateInterestRates( + dai.address, + aDai.address, + 0, + 0, + 0, + 0, + 0, + strategyDAI.reserveFactor + ); -// const {DAI: daiConfiguration} = _reservesParams + expect(currentLiquidityRate.toString()).to.be.equal('0', 'Invalid liquidity rate'); + expect(currentStableBorrowRate.toString()).to.be.equal( + new BigNumber(0.039).times(RAY).toFixed(0), + 'Invalid stable rate' + ); + expect(currentVariableBorrowRate.toString()).to.be.equal( + rateStrategyStableOne.baseVariableBorrowRate, + 'Invalid variable rate' + ); + }); -// const contract: any = await artifacts.require("DefaultReserveInterestRateStrategy") -// const mathLibrary = await artifacts.require("WadRayMath") -// const mathLibraryInstance = await mathLibrary.new() + it('Checks rates at 80% utilization rate', async () => { + const { + 0: currentLiquidityRate, + 1: currentStableBorrowRate, + 2: currentVariableBorrowRate, + } = await strategyInstance.calculateInterestRates( + dai.address, + aDai.address, + '200000000000000000', + '0', + '0', + '800000000000000000', + '0', + strategyDAI.reserveFactor + ); -// await contract.link("WadRayMath", mathLibraryInstance.address) + const expectedVariableRate = new BigNumber(rateStrategyStableOne.baseVariableBorrowRate).plus( + rateStrategyStableOne.variableRateSlope1 + ); -// _strategyInstance = await contract.new( -// daiInstance.address, -// _addressesProviderInstance.address, -// daiConfiguration.baseVariableBorrowRate, -// daiConfiguration.variableRateSlope1, -// daiConfiguration.variableRateSlope2, -// daiConfiguration.stableRateSlope1, -// daiConfiguration.stableRateSlope2, -// ) -// }) + expect(currentLiquidityRate.toString()).to.be.equal( + expectedVariableRate + .times(0.8) + .percentMul(new BigNumber(PERCENTAGE_FACTOR).minus(strategyDAI.reserveFactor)) + .toFixed(0), + 'Invalid liquidity rate' + ); -// it("Checks rates at 0% utilization rate", async () => { -// const {DAI: daiInstance} = _tokenInstances -// const {DAI: daiConfiguration} = _reservesParams -// const data: any = await _strategyInstance.calculateInterestRates( -// daiInstance.address, -// "1000000000000000000", -// "0", -// "0", -// "0", -// ) + expect(currentVariableBorrowRate.toString()).to.be.equal( + expectedVariableRate.toFixed(0), + 'Invalid variable rate' + ); -// expect(data.currentLiquidityRate.toString()).to.be.equal("0", "Invalid liquidity rate") -// expect(data.currentStableBorrowRate.toString()).to.be.equal( -// new BigNumber(0.039).times(RAY).toFixed(0), -// "Invalid stable rate", -// ) -// expect(data.currentVariableBorrowRate.toString()).to.be.equal( -// daiConfiguration.baseVariableBorrowRate, -// "Invalid variable rate", -// ) -// }) + expect(currentStableBorrowRate.toString()).to.be.equal( + new BigNumber(0.039).times(RAY).plus(rateStrategyStableOne.stableRateSlope1).toFixed(0), + 'Invalid stable rate' + ); + }); -// it("Checks rates at 80% utilization rate", async () => { -// const {DAI: daiInstance} = _tokenInstances -// const {DAI: daiConfiguration} = _reservesParams -// const data: any = await _strategyInstance.calculateInterestRates( -// daiInstance.address, -// "200000000000000000", -// "0", -// "800000000000000000", -// "0", -// ) + it('Checks rates at 100% utilization rate', async () => { + const { + 0: currentLiquidityRate, + 1: currentStableBorrowRate, + 2: currentVariableBorrowRate, + } = await strategyInstance.calculateInterestRates( + dai.address, + aDai.address, + '0', + '0', + '0', + '800000000000000000', + '0', + strategyDAI.reserveFactor + ); -// const expectedVariableRate = new BigNumber(daiConfiguration.baseVariableBorrowRate) -// .plus(daiConfiguration.variableRateSlope1) + const expectedVariableRate = new BigNumber(rateStrategyStableOne.baseVariableBorrowRate) + .plus(rateStrategyStableOne.variableRateSlope1) + .plus(rateStrategyStableOne.variableRateSlope2); -// expect(data.currentLiquidityRate.toString()).to.be.equal( -// expectedVariableRate.times(0.8).toFixed(0), -// "Invalid liquidity rate", -// ) + expect(currentLiquidityRate.toString()).to.be.equal( + expectedVariableRate + .percentMul(new BigNumber(PERCENTAGE_FACTOR).minus(strategyDAI.reserveFactor)) + .toFixed(0), + 'Invalid liquidity rate' + ); -// expect(data.currentVariableBorrowRate.toString()).to.be.equal( -// new BigNumber(daiConfiguration.baseVariableBorrowRate) -// .plus(daiConfiguration.variableRateSlope1) -// .toFixed(0), -// "Invalid variable rate", -// ) + expect(currentVariableBorrowRate.toString()).to.be.equal( + expectedVariableRate.toFixed(0), + 'Invalid variable rate' + ); -// expect(data.currentStableBorrowRate.toString()).to.be.equal( -// new BigNumber(0.039) -// .times(RAY) -// .plus(daiConfiguration.stableRateSlope1) -// .toFixed(0), -// "Invalid stable rate", -// ) -// }) + expect(currentStableBorrowRate.toString()).to.be.equal( + new BigNumber(0.039) + .times(RAY) + .plus(rateStrategyStableOne.stableRateSlope1) + .plus(rateStrategyStableOne.stableRateSlope2) + .toFixed(0), + 'Invalid stable rate' + ); + }); -// it("Checks rates at 100% utilization rate", async () => { -// const {DAI: daiInstance} = _tokenInstances -// const {DAI: daiConfiguration} = _reservesParams -// const data: any = await _strategyInstance.calculateInterestRates( -// daiInstance.address, -// "0", -// "0", -// "1000000000000000000", -// "0", -// ) + it('Checks rates at 100% utilization rate, 50% stable debt and 50% variable debt, with a 10% avg stable rate', async () => { + const { + 0: currentLiquidityRate, + 1: currentStableBorrowRate, + 2: currentVariableBorrowRate, + } = await strategyInstance.calculateInterestRates( + dai.address, + aDai.address, + '0', + '0', + '400000000000000000', + '400000000000000000', + '100000000000000000000000000', + strategyDAI.reserveFactor + ); -// const expectedVariableRate = new BigNumber(daiConfiguration.baseVariableBorrowRate) -// .plus(daiConfiguration.variableRateSlope1) -// .plus(daiConfiguration.variableRateSlope2) -// .toFixed(0) + const expectedVariableRate = new BigNumber(rateStrategyStableOne.baseVariableBorrowRate) + .plus(rateStrategyStableOne.variableRateSlope1) + .plus(rateStrategyStableOne.variableRateSlope2); -// expect(data.currentLiquidityRate.toString()).to.be.equal( -// expectedVariableRate, -// "Invalid liquidity rate", -// ) + const expectedLiquidityRate = new BigNumber( + currentVariableBorrowRate.add('100000000000000000000000000').div(2).toString() + ) + .percentMul(new BigNumber(PERCENTAGE_FACTOR).minus(strategyDAI.reserveFactor)) + .toFixed(0); -// expect(data.currentVariableBorrowRate.toString()).to.be.equal( -// expectedVariableRate, -// "Invalid variable rate", -// ) + expect(currentLiquidityRate.toString()).to.be.equal( + expectedLiquidityRate, + 'Invalid liquidity rate' + ); -// expect(data.currentStableBorrowRate.toString()).to.be.equal( -// new BigNumber(0.039) -// .times(RAY) -// .plus(daiConfiguration.stableRateSlope1) -// .plus(daiConfiguration.stableRateSlope2) -// .toFixed(0), -// "Invalid stable rate", -// ) -// }) -// }) + expect(currentVariableBorrowRate.toString()).to.be.equal( + expectedVariableRate.toFixed(0), + 'Invalid variable rate' + ); + + expect(currentStableBorrowRate.toString()).to.be.equal( + new BigNumber(0.039) + .times(RAY) + .plus(rateStrategyStableOne.stableRateSlope1) + .plus(rateStrategyStableOne.stableRateSlope2) + .toFixed(0), + 'Invalid stable rate' + ); + }); +}); diff --git a/test-suites/test-amm/rate-strategy.spec.ts b/test-suites/test-amm/rate-strategy.spec.ts deleted file mode 100644 index b56c754e..00000000 --- a/test-suites/test-amm/rate-strategy.spec.ts +++ /dev/null @@ -1,165 +0,0 @@ -// import { -// IReserveParams, -// iAavePoolAssets, -// iAssetsWithoutETH, -// ITestEnvWithoutInstances, -// } from "../utils/types" -// import { - -// LendingPoolAddressesProviderInstance, - -// DefaultReserveInterestRateStrategyInstance, -// MintableERC20Instance, -// } from "../utils/typechain-types/truffle-contracts" -// import { testEnvProviderWithoutInstances} from "../utils/truffle/dlp-tests-env" -// import {RAY} from "../utils/constants" -// import BigNumber from "bignumber.js" - -// const {expect} = require("chai") - -// contract("Interest rate strategy", async ([deployer, ...users]) => { -// let _testEnvProvider: ITestEnvWithoutInstances -// let _strategyInstance: DefaultReserveInterestRateStrategyInstance -// let _tokenInstances: iAssetsWithoutETH -// let _addressesProviderInstance: LendingPoolAddressesProviderInstance -// let _reservesParams: iAavePoolAssets - -// before("Initializing test variables", async () => { -// console.time('setup-test'); -// _testEnvProvider = await testEnvProviderWithoutInstances( -// artifacts, -// [deployer, ...users], -// ) - -// const { -// getAllAssetsInstances, -// getLendingPoolAddressesProviderInstance, -// getAavePoolReservesParams, -// } = _testEnvProvider - -// const instances = await Promise.all([ -// getAllAssetsInstances(), -// getLendingPoolAddressesProviderInstance() -// ]) - -// _tokenInstances = instances[0] -// _addressesProviderInstance = instances[1] -// _reservesParams = await getAavePoolReservesParams() -// console.timeEnd('setup-test'); -// }) - -// it("Deploys a new instance of a DefaultReserveInterestRateStrategy contract", async () => { -// const {DAI: daiInstance} = _tokenInstances - -// const {DAI: daiConfiguration} = _reservesParams - -// const contract: any = await artifacts.require("DefaultReserveInterestRateStrategy") -// const mathLibrary = await artifacts.require("WadRayMath") -// const mathLibraryInstance = await mathLibrary.new() - -// await contract.link("WadRayMath", mathLibraryInstance.address) - -// _strategyInstance = await contract.new( -// daiInstance.address, -// _addressesProviderInstance.address, -// daiConfiguration.baseVariableBorrowRate, -// daiConfiguration.variableRateSlope1, -// daiConfiguration.variableRateSlope2, -// daiConfiguration.stableRateSlope1, -// daiConfiguration.stableRateSlope2, -// ) -// }) - -// it("Checks rates at 0% utilization rate", async () => { -// const {DAI: daiInstance} = _tokenInstances -// const {DAI: daiConfiguration} = _reservesParams -// const data: any = await _strategyInstance.calculateInterestRates( -// daiInstance.address, -// "1000000000000000000", -// "0", -// "0", -// "0", -// ) - -// expect(data.currentLiquidityRate.toString()).to.be.equal("0", "Invalid liquidity rate") -// expect(data.currentStableBorrowRate.toString()).to.be.equal( -// new BigNumber(0.039).times(RAY).toFixed(0), -// "Invalid stable rate", -// ) -// expect(data.currentVariableBorrowRate.toString()).to.be.equal( -// daiConfiguration.baseVariableBorrowRate, -// "Invalid variable rate", -// ) -// }) - -// it("Checks rates at 80% utilization rate", async () => { -// const {DAI: daiInstance} = _tokenInstances -// const {DAI: daiConfiguration} = _reservesParams -// const data: any = await _strategyInstance.calculateInterestRates( -// daiInstance.address, -// "200000000000000000", -// "0", -// "800000000000000000", -// "0", -// ) - -// const expectedVariableRate = new BigNumber(daiConfiguration.baseVariableBorrowRate) -// .plus(daiConfiguration.variableRateSlope1) - -// expect(data.currentLiquidityRate.toString()).to.be.equal( -// expectedVariableRate.times(0.8).toFixed(0), -// "Invalid liquidity rate", -// ) - -// expect(data.currentVariableBorrowRate.toString()).to.be.equal( -// new BigNumber(daiConfiguration.baseVariableBorrowRate) -// .plus(daiConfiguration.variableRateSlope1) -// .toFixed(0), -// "Invalid variable rate", -// ) - -// expect(data.currentStableBorrowRate.toString()).to.be.equal( -// new BigNumber(0.039) -// .times(RAY) -// .plus(daiConfiguration.stableRateSlope1) -// .toFixed(0), -// "Invalid stable rate", -// ) -// }) - -// it("Checks rates at 100% utilization rate", async () => { -// const {DAI: daiInstance} = _tokenInstances -// const {DAI: daiConfiguration} = _reservesParams -// const data: any = await _strategyInstance.calculateInterestRates( -// daiInstance.address, -// "0", -// "0", -// "1000000000000000000", -// "0", -// ) - -// const expectedVariableRate = new BigNumber(daiConfiguration.baseVariableBorrowRate) -// .plus(daiConfiguration.variableRateSlope1) -// .plus(daiConfiguration.variableRateSlope2) -// .toFixed(0) - -// expect(data.currentLiquidityRate.toString()).to.be.equal( -// expectedVariableRate, -// "Invalid liquidity rate", -// ) - -// expect(data.currentVariableBorrowRate.toString()).to.be.equal( -// expectedVariableRate, -// "Invalid variable rate", -// ) - -// expect(data.currentStableBorrowRate.toString()).to.be.equal( -// new BigNumber(0.039) -// .times(RAY) -// .plus(daiConfiguration.stableRateSlope1) -// .plus(daiConfiguration.stableRateSlope2) -// .toFixed(0), -// "Invalid stable rate", -// ) -// }) -// }) From befb4471482d11b42f15194ed8ba80817225abf2 Mon Sep 17 00:00:00 2001 From: David Racero Date: Tue, 2 Mar 2021 17:21:04 +0100 Subject: [PATCH 170/219] Added configs to support tenderly fork rpcs. Added new price feeds addresses. Fix owner signer issues. --- docker-compose.test.yml | 1 + docker-compose.yml | 1 + helper-hardhat-config.ts | 34 ++++++----- helpers/contracts-helpers.ts | 5 +- markets/amm/commons.ts | 96 +++++++++++++++++--------------- package.json | 1 + tasks/full/1_address_provider.ts | 8 +-- tasks/full/3_oracles.ts | 11 +++- tasks/misc/initialize-tokens.ts | 8 +-- 9 files changed, 88 insertions(+), 77 deletions(-) diff --git a/docker-compose.test.yml b/docker-compose.test.yml index d71c1956..ceb59e73 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -7,3 +7,4 @@ services: environment: - MNEMONIC - ALCHEMY_KEY + - TENDERLY_FORK_ID diff --git a/docker-compose.yml b/docker-compose.yml index f6cca30f..5500aac7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,3 +19,4 @@ services: TENDERLY_PROJECT: ${TENDERLY_PROJECT} TENDERLY_USERNAME: ${TENDERLY_USERNAME} ALCHEMY_KEY: ${ALCHEMY_KEY} + TENDERLY_FORK_ID: ${TENDERLY_FORK_ID} diff --git a/helper-hardhat-config.ts b/helper-hardhat-config.ts index c25f7b9f..552a2e52 100644 --- a/helper-hardhat-config.ts +++ b/helper-hardhat-config.ts @@ -1,10 +1,16 @@ // @ts-ignore -import { eEthereumNetwork, ePolygonNetwork, eXDaiNetwork, iParamsPerNetwork } from './helpers/types'; +import { + eEthereumNetwork, + ePolygonNetwork, + eXDaiNetwork, + iParamsPerNetwork, +} from './helpers/types'; require('dotenv').config(); const INFURA_KEY = process.env.INFURA_KEY || ''; const ALCHEMY_KEY = process.env.ALCHEMY_KEY || ''; +const TENDERLY_FORK_ID = process.env.TENDERLY_FORK_ID || ''; const GWEI = 1000 * 1000 * 1000; @@ -21,23 +27,21 @@ export const NETWORKS_RPC_URL: iParamsPerNetwork = { [eEthereumNetwork.coverage]: 'http://localhost:8555', [eEthereumNetwork.hardhat]: 'http://localhost:8545', [eEthereumNetwork.buidlerevm]: 'http://localhost:8545', - [eEthereumNetwork.tenderlyMain]: ALCHEMY_KEY - ? `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}` - : `https://mainnet.infura.io/v3/${INFURA_KEY}`, + [eEthereumNetwork.tenderlyMain]: `https://rpc.tenderly.co/fork/${TENDERLY_FORK_ID}`, [ePolygonNetwork.mumbai]: 'https://rpc-mumbai.maticvigil.com', [ePolygonNetwork.matic]: 'https://rpc-mainnet.matic.network', [eXDaiNetwork.xdai]: 'https://rpc.xdaichain.com/', -} +}; export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { - [eEthereumNetwork.kovan]: 65 * GWEI , - [eEthereumNetwork.ropsten]: 65 * GWEI , - [eEthereumNetwork.main]: 65 * GWEI , - [eEthereumNetwork.coverage]: 65 * GWEI , - [eEthereumNetwork.hardhat]: 65 * GWEI , - [eEthereumNetwork.buidlerevm]: 65 * GWEI , - [eEthereumNetwork.tenderlyMain]: 65 * GWEI , - [ePolygonNetwork.mumbai]: 1 * GWEI , - [ePolygonNetwork.matic]: 2 * GWEI , + [eEthereumNetwork.kovan]: 65 * GWEI, + [eEthereumNetwork.ropsten]: 65 * GWEI, + [eEthereumNetwork.main]: 65 * GWEI, + [eEthereumNetwork.coverage]: 65 * GWEI, + [eEthereumNetwork.hardhat]: 65 * GWEI, + [eEthereumNetwork.buidlerevm]: 65 * GWEI, + [eEthereumNetwork.tenderlyMain]: 0.01 * GWEI, + [ePolygonNetwork.mumbai]: 1 * GWEI, + [ePolygonNetwork.matic]: 2 * GWEI, [eXDaiNetwork.xdai]: 1 * GWEI, -} \ No newline at end of file +}; diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index d7e50664..455dbb78 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -99,11 +99,14 @@ export const withSaveAndVerify = async ( await waitForTx(instance.deployTransaction); await registerContractInJsonDb(id, instance); if (usingTenderly()) { - console.log('doing verify of', id); + console.log(); + console.log('Doing Tenderly contract verification of', id); await (DRE as any).tenderlyRPC.verify({ name: id, address: instance.address, }); + console.log(`Verified ${id} at Tenderly!`); + console.log(); } if (verify) { await verifyContract(instance.address, args); diff --git a/markets/amm/commons.ts b/markets/amm/commons.ts index ce8614a8..b892064d 100644 --- a/markets/amm/commons.ts +++ b/markets/amm/commons.ts @@ -1,5 +1,11 @@ import BigNumber from 'bignumber.js'; -import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants'; +import { + oneEther, + oneRay, + RAY, + ZERO_ADDRESS, + MOCK_CHAINLINK_AGGREGATORS_PRICES, +} from '../../helpers/constants'; import { ICommonConfiguration, eEthereumNetwork } from '../../helpers/types'; // ---------------- @@ -54,7 +60,7 @@ export const CommonsConfig: ICommonConfiguration = { UniWBTCWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, - UniAAVEWETH:{ + UniAAVEWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, UniBATWETH: { @@ -95,7 +101,7 @@ export const CommonsConfig: ICommonConfiguration = { }, BptBALWETH: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), - } + }, }, // ---------------- // COMMON PROTOCOL ADDRESSES ACROSS POOLS @@ -132,7 +138,8 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', }, - ProviderRegistryOwner: { // DEPLOYED WITH CORRECT ADDRESS + ProviderRegistryOwner: { + // DEPLOYED WITH CORRECT ADDRESS [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', @@ -144,8 +151,8 @@ export const CommonsConfig: ICommonConfiguration = { LendingRateOracle: { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', - [eEthereumNetwork.buidlerevm]: '',// Updated to match Kovan deployment - [eEthereumNetwork.kovan]: '0xd00Bd28FAdDa9d5658D1D4e0c151973146C7A533',//'0xE48F95873855bfd97BF89572DDf5cBC44D9c545b' + [eEthereumNetwork.buidlerevm]: '', // Updated to match Kovan deployment + [eEthereumNetwork.kovan]: '0xd00Bd28FAdDa9d5658D1D4e0c151973146C7A533', //'0xE48F95873855bfd97BF89572DDf5cBC44D9c545b' [eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b', [eEthereumNetwork.main]: '', //'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', // Need to re-deploy because of onlyOwner [eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', @@ -201,7 +208,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.buidlerevm]: '', [eEthereumNetwork.kovan]: '0x8fb777d67e9945e2c01936e319057f9d41d559e6', // Need to re-deploy because of onlyOwner [eEthereumNetwork.ropsten]: ZERO_ADDRESS, - [eEthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', // Need to re-deploy because of onlyOwner + [eEthereumNetwork.main]: '', //'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', // Need to re-deploy because of onlyOwner [eEthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', }, FallbackOracle: { @@ -221,9 +228,9 @@ export const CommonsConfig: ICommonConfiguration = { USDT: '0x0bF499444525a23E7Bb61997539725cA2e928138', WBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25', USDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', - DAI:'0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', - UniDAIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', // Mock oracles - UniWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', + DAI: '0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', + UniDAIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', // Mock oracles + UniWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', UniAAVEWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', UniBATWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', UniDAIUSDC: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', @@ -240,52 +247,51 @@ export const CommonsConfig: ICommonConfiguration = { BptBALWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, - [eEthereumNetwork.ropsten]: { - }, + [eEthereumNetwork.ropsten]: {}, [eEthereumNetwork.main]: { USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', - DAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', + DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', UniDAIWETH: '0xf4071801C4421Db7e63DaC15B9432e50C44a7F42', - UniWBTCWETH: ZERO_ADDRESS, - UniAAVEWETH: ZERO_ADDRESS, - UniBATWETH: ZERO_ADDRESS, - UniDAIUSDC: ZERO_ADDRESS, - UniCRVWETH: ZERO_ADDRESS, - UniLINKWETH: ZERO_ADDRESS, - UniMKRWETH: ZERO_ADDRESS, - UniRENWETH: ZERO_ADDRESS, - UniSNXWETH: ZERO_ADDRESS, - UniUNIWETH: ZERO_ADDRESS, - UniUSDCWETH: ZERO_ADDRESS, - UniWBTCUSDC: ZERO_ADDRESS, - UniYFIWETH: ZERO_ADDRESS, - BptWBTCWETH: ZERO_ADDRESS, - BptBALWETH: ZERO_ADDRESS, + UniWBTCWETH: '0x55EF7F1226507cFd846DE009C2f097c2211b6Fb8', + UniAAVEWETH: '0x5671387d56eAB334A2D65d6D0BB4D907898C7abA', + UniBATWETH: '0xA61ca04DF33B72b235a8A28CfB535bb7A5271B70', + UniDAIUSDC: '0xFd8dFc92B030e6BA957336e9f08C2a711e19069A', + UniCRVWETH: '0xd4D344D076256Fdf806375983b2cab2Db52FD506', + UniLINKWETH: '0x8C0e5df19B998F06e57A1Db1a38232F7590abe4b', + UniMKRWETH: '0x92f2A28fE33E0b6Ea218057EEe004E3B2B6de45d', + UniRENWETH: '0xFc0398b247107138dB494395600fB0d075b72C9A', + UniSNXWETH: '0xF5CB13c859383B5fb070bd111Cae7a900c00BA07', + UniUNIWETH: '0xE50e47E37DCF55dE1c5F2c32d346BB52064f7CE6', + UniUSDCWETH: '0xBE6ac123799572c98eFdE48895465AB392534AFD', + UniWBTCUSDC: '0xd6b8b08a0d13994A5f4a1949F4870DE57e9B40d9', + UniYFIWETH: '0x94daB35789f05f54224F6851921160DE21318072', + BptWBTCWETH: '0x4a2731c9f3B4355922c676f9b538278D79C299C5', + BptBALWETH: '0xD9400999f38E1877a6dDDb0090A327F19257f9AE', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [eEthereumNetwork.tenderlyMain]: { USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46', WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', - DAI:'0x773616E4d11A78F511299002da57A0a94577F1f4', - UniDAIWETH: ZERO_ADDRESS, - UniWBTCWETH: ZERO_ADDRESS, - UniAAVEWETH: ZERO_ADDRESS, - UniBATWETH: ZERO_ADDRESS, - UniDAIUSDC: ZERO_ADDRESS, - UniCRVWETH: ZERO_ADDRESS, - UniLINKWETH: ZERO_ADDRESS, - UniMKRWETH: ZERO_ADDRESS, - UniRENWETH: ZERO_ADDRESS, - UniSNXWETH: ZERO_ADDRESS, - UniUNIWETH: ZERO_ADDRESS, - UniUSDCWETH: ZERO_ADDRESS, - UniWBTCUSDC: ZERO_ADDRESS, - UniYFIWETH: ZERO_ADDRESS, - BptWBTCWETH: ZERO_ADDRESS, - BptBALWETH: ZERO_ADDRESS, + DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', + UniDAIWETH: '0xf4071801C4421Db7e63DaC15B9432e50C44a7F42', + UniWBTCWETH: '0x55EF7F1226507cFd846DE009C2f097c2211b6Fb8', + UniAAVEWETH: '0x5671387d56eAB334A2D65d6D0BB4D907898C7abA', + UniBATWETH: '0xA61ca04DF33B72b235a8A28CfB535bb7A5271B70', + UniDAIUSDC: '0xFd8dFc92B030e6BA957336e9f08C2a711e19069A', + UniCRVWETH: '0xd4D344D076256Fdf806375983b2cab2Db52FD506', + UniLINKWETH: '0x8C0e5df19B998F06e57A1Db1a38232F7590abe4b', + UniMKRWETH: '0x92f2A28fE33E0b6Ea218057EEe004E3B2B6de45d', + UniRENWETH: '0xFc0398b247107138dB494395600fB0d075b72C9A', + UniSNXWETH: '0xF5CB13c859383B5fb070bd111Cae7a900c00BA07', + UniUNIWETH: '0xE50e47E37DCF55dE1c5F2c32d346BB52064f7CE6', + UniUSDCWETH: '0xBE6ac123799572c98eFdE48895465AB392534AFD', + UniWBTCUSDC: '0xd6b8b08a0d13994A5f4a1949F4870DE57e9B40d9', + UniYFIWETH: '0x94daB35789f05f54224F6851921160DE21318072', + BptWBTCWETH: '0x4a2731c9f3B4355922c676f9b538278D79C299C5', + BptBALWETH: '0xD9400999f38E1877a6dDDb0090A327F19257f9AE', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, }, diff --git a/package.json b/package.json index 2b3703c4..c2214791 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "aave:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- aave:mainnet", "aave:fork:main": "npm run compile && MAINNET_FORK=true hardhat aave:mainnet", "amm:fork:main": "npm run compile && MAINNET_FORK=true hardhat amm:mainnet", + "amm:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- amm:mainnet", "aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify", "aave:main:full:initialize": "npm run compile && MAINNET_FORK=true full:initialize-tokens --pool Aave", "amm:main:full:migration": "npm run compile && npm run hardhat:main -- amm:mainnet --verify", diff --git a/tasks/full/1_address_provider.ts b/tasks/full/1_address_provider.ts index 88852c0c..d9563ebc 100644 --- a/tasks/full/1_address_provider.ts +++ b/tasks/full/1_address_provider.ts @@ -64,13 +64,7 @@ task( const firstAccount = await getFirstSigner(); await firstAccount.sendTransaction({ value: parseEther('10'), to: providerRegistryOwner }); } else { - signer = await getFirstSigner(); - const deployerAddress = await signer.getAddress(); - if (providerRegistryOwner !== (await signer.getAddress())) { - throw Error( - `Current signer is not provider registry owner. \nCurrent deployer address: ${deployerAddress} \nExpected address: ${poolConfig.ProviderRegistryOwner}` - ); - } + signer = DRE.ethers.provider.getSigner(providerRegistryOwner); } // 1. Address Provider Registry instance const addressesProviderRegistry = ( diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index e479b6b1..e3f8f27f 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -50,7 +50,11 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') let aaveOracle: AaveOracle; if (notFalsyOrZeroAddress(aaveOracleAddress)) { - aaveOracle = await getAaveOracle(aaveOracleAddress); + aaveOracle = await await getAaveOracle(aaveOracleAddress); + const owner = await aaveOracle.owner(); + const signer = DRE.ethers.provider.getSigner(owner); + + aaveOracle = await (await getAaveOracle(aaveOracleAddress)).connect(signer); await waitForTx(await aaveOracle.setAssetSources(tokens, aggregators)); } else { aaveOracle = await deployAaveOracle( @@ -59,11 +63,14 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') ); } - const lendingRateOracle = notFalsyOrZeroAddress(lendingRateOracleAddress) + let lendingRateOracle = notFalsyOrZeroAddress(lendingRateOracleAddress) ? await getLendingRateOracle(lendingRateOracleAddress) : await deployLendingRateOracle(verify); const { USD, ...tokensAddressesWithoutUsd } = tokensToWatch; + lendingRateOracle = lendingRateOracle.connect( + DRE.ethers.provider.getSigner(await lendingRateOracle.owner()) + ); // This must be done any time a new market is created I believe //if (!lendingRateOracleAddress) { await setInitialMarketRatesInRatesOracleByHelper( diff --git a/tasks/misc/initialize-tokens.ts b/tasks/misc/initialize-tokens.ts index 680e1337..342e6e1a 100644 --- a/tasks/misc/initialize-tokens.ts +++ b/tasks/misc/initialize-tokens.ts @@ -60,13 +60,7 @@ task('full:initialize-tokens', 'Initialize lending pool configuration.') const balance = await signer.getBalance(); console.log('signer balance', formatEther(balance)); } else { - signer = await getFirstSigner(); - const deployerAddress = await signer.getAddress(); - if (providerRegistryOwner !== (await signer.getAddress())) { - throw Error( - `Current signer is not provider registry owner. \nCurrent deployer address: ${deployerAddress} \nExpected address: ${poolConfig.ProviderRegistryOwner}` - ); - } + signer = DRE.ethers.provider.getSigner(providerRegistryOwner); } // Init unitilialized reserves From d9026b712254277ffa854eea102fe03616680312 Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 3 Mar 2021 12:25:10 +0100 Subject: [PATCH 171/219] Support fork connection. --- docker-compose.test.yml | 1 - docker-compose.yml | 1 + hardhat.config.ts | 6 +++--- package.json | 2 +- tasks/migrations/aave.mainnet.ts | 5 ++++- tasks/migrations/amm.mainnet.ts | 5 ++++- tasks/migrations/matic.mainnet.ts | 7 +++++-- tasks/misc/set-bre.ts | 20 ++++++++++++++++++-- 8 files changed, 36 insertions(+), 11 deletions(-) diff --git a/docker-compose.test.yml b/docker-compose.test.yml index ceb59e73..d71c1956 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -7,4 +7,3 @@ services: environment: - MNEMONIC - ALCHEMY_KEY - - TENDERLY_FORK_ID diff --git a/docker-compose.yml b/docker-compose.yml index 5500aac7..7c94bcb3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,3 +20,4 @@ services: TENDERLY_USERNAME: ${TENDERLY_USERNAME} ALCHEMY_KEY: ${ALCHEMY_KEY} TENDERLY_FORK_ID: ${TENDERLY_FORK_ID} + TENDERLY_HEAD_ID: ${TENDERLY_HEAD_ID} diff --git a/hardhat.config.ts b/hardhat.config.ts index 47c26680..0c6fa1e1 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -5,8 +5,8 @@ import { HardhatUserConfig } from 'hardhat/types'; import { accounts } from './test-wallets.js'; import { eEthereumNetwork, eNetwork, ePolygonNetwork, eXDaiNetwork } from './helpers/types'; import { BUIDLEREVM_CHAINID, COVERAGE_CHAINID } from './helpers/buidler-constants'; -import { NETWORKS_RPC_URL, NETWORKS_DEFAULT_GAS } from './helper-hardhat-config'; - +import { NETWORKS_RPC_URL, NETWORKS_DEFAULT_GAS } from './helper-hardhat-config'; + require('dotenv').config(); import '@nomiclabs/hardhat-ethers'; @@ -94,7 +94,7 @@ const buidlerConfig: HardhatUserConfig = { kovan: getCommonNetworkConfig(eEthereumNetwork.kovan, 42), ropsten: getCommonNetworkConfig(eEthereumNetwork.ropsten, 3), main: getCommonNetworkConfig(eEthereumNetwork.main, 1), - tenderlyMain: getCommonNetworkConfig(eEthereumNetwork.main, 1), + tenderlyMain: getCommonNetworkConfig(eEthereumNetwork.tenderlyMain, 3030), matic: getCommonNetworkConfig(ePolygonNetwork.matic, 137), mumbai: getCommonNetworkConfig(ePolygonNetwork.mumbai, 80001), xdai: getCommonNetworkConfig(eXDaiNetwork.xdai, 100), diff --git a/package.json b/package.json index c2214791..4532f6fa 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "@nomiclabs/hardhat-ethers": "^2.0.0", "@nomiclabs/hardhat-waffle": "^2.0.0", "@openzeppelin/contracts": "3.1.0", - "@tenderly/hardhat-tenderly": "^1.1.0-beta.3", + "@tenderly/hardhat-tenderly": "^1.1.0-beta.4", "@typechain/ethers-v4": "1.0.0", "@typechain/ethers-v5": "^2.0.0", "@typechain/truffle-v4": "2.0.2", diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index 19649262..184f6e47 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -46,7 +46,10 @@ task('aave:mainnet', 'Deploy development enviroment') if (usingTenderly()) { const postDeployHead = DRE.tenderlyRPC.getHead(); - console.log('Tenderly UUID', postDeployHead); + const postDeployFork = DRE.tenderlyRPC.getFork(); + console.log('Tenderly Info'); + console.log('- Head', postDeployHead); + console.log('- Fork', postDeployFork); } console.log('\nFinished migrations'); printContracts(); diff --git a/tasks/migrations/amm.mainnet.ts b/tasks/migrations/amm.mainnet.ts index 3d0e6c8b..e496fc82 100644 --- a/tasks/migrations/amm.mainnet.ts +++ b/tasks/migrations/amm.mainnet.ts @@ -46,7 +46,10 @@ task('amm:mainnet', 'Deploy development enviroment') if (usingTenderly()) { const postDeployHead = DRE.tenderlyRPC.getHead(); - console.log('Tenderly UUID', postDeployHead); + const postDeployFork = DRE.tenderlyRPC.getFork(); + console.log('Tenderly Info'); + console.log('- Head', postDeployHead); + console.log('- Fork', postDeployFork); } console.log('\nFinished migrations'); printContracts(); diff --git a/tasks/migrations/matic.mainnet.ts b/tasks/migrations/matic.mainnet.ts index 970fbfc9..5c2f7f09 100644 --- a/tasks/migrations/matic.mainnet.ts +++ b/tasks/migrations/matic.mainnet.ts @@ -21,7 +21,7 @@ task('matic:mainnet', 'Deploy development enviroment') await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); console.log('2. Deploy lending pool'); - await DRE.run('full:deploy-lending-pool', { pool: POOL_NAME}); + await DRE.run('full:deploy-lending-pool', { pool: POOL_NAME }); console.log('3. Deploy oracles'); await DRE.run('full:deploy-oracles', { pool: POOL_NAME }); @@ -43,7 +43,10 @@ task('matic:mainnet', 'Deploy development enviroment') if (usingTenderly()) { const postDeployHead = DRE.tenderlyRPC.getHead(); - console.log('Tenderly UUID', postDeployHead); + const postDeployFork = DRE.tenderlyRPC.getFork(); + console.log('Tenderly Info'); + console.log('- Head', postDeployHead); + console.log('- Fork', postDeployFork); } console.log('\nFinished migrations'); printContracts(); diff --git a/tasks/misc/set-bre.ts b/tasks/misc/set-bre.ts index e2aeba12..63721451 100644 --- a/tasks/misc/set-bre.ts +++ b/tasks/misc/set-bre.ts @@ -3,6 +3,8 @@ import { DRE, setDRE } from '../../helpers/misc-utils'; import { EthereumNetworkNames } from '../../helpers/types'; import { usingTenderly } from '../../helpers/tenderly-utils'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { getFirstSigner } from '../../helpers/contracts-getters'; +import { formatEther } from 'ethers/lib/utils'; task(`set-DRE`, `Inits the DRE, to have access to all the plugins' objects`).setAction( async (_, _DRE) => { @@ -14,10 +16,24 @@ task(`set-DRE`, `Inits the DRE, to have access to all the plugins' objects`).set process.env.TENDERLY === 'true' ) { console.log('- Setting up Tenderly provider'); - await _DRE.tenderlyRPC.initializeFork(); - console.log('- Initialized Tenderly fork'); + if (process.env.TENDERLY_FORK_ID && process.env.TENDERLY_HEAD_ID) { + console.log('- Connecting to a Tenderly Fork'); + _DRE.tenderlyRPC.setFork(process.env.TENDERLY_FORK_ID); + _DRE.tenderlyRPC.setHead(process.env.TENDERLY_HEAD_ID); + } else { + console.log('- Creating a new Tenderly Fork'); + await _DRE.tenderlyRPC.initializeFork(); + } const provider = new _DRE.ethers.providers.Web3Provider(_DRE.tenderlyRPC as any); _DRE.ethers.provider = provider; + console.log('- Initialized Tenderly fork:'); + console.log(' - Fork: ', _DRE.tenderlyRPC.getFork()); + console.log(' - Head: ', _DRE.tenderlyRPC.getHead()); + console.log(' - First account:', await (await _DRE.ethers.getSigners())[0].getAddress()); + console.log( + ' - Balance:', + formatEther(await (await _DRE.ethers.getSigners())[0].getBalance()) + ); } setDRE(_DRE); From 7f44a0c2422cf08290a7a35b5652b5ef43d4d22f Mon Sep 17 00:00:00 2001 From: The3D Date: Fri, 5 Mar 2021 10:36:55 +0100 Subject: [PATCH 172/219] Removed unused param in struct --- .../IReserveInterestRateStrategy.sol | 16 +++++ .../DefaultReserveInterestRateStrategy.sol | 68 +++++++++++++++---- test-suites/test-aave/rate-strategy.spec.ts | 8 +-- 3 files changed, 75 insertions(+), 17 deletions(-) diff --git a/contracts/interfaces/IReserveInterestRateStrategy.sol b/contracts/interfaces/IReserveInterestRateStrategy.sol index 70eb99ee..cee593cb 100644 --- a/contracts/interfaces/IReserveInterestRateStrategy.sol +++ b/contracts/interfaces/IReserveInterestRateStrategy.sol @@ -11,6 +11,22 @@ interface IReserveInterestRateStrategy { function getMaxVariableBorrowRate() external view returns (uint256); + function calculateInterestRates( + address reserve, + uint256 availableLiquidity, + uint256 totalStableDebt, + uint256 totalVariableDebt, + uint256 averageStableBorrowRate, + uint256 reserveFactor + ) + external + view + returns ( + uint256, + uint256, + uint256 + ); + function calculateInterestRates( address reserve, address aToken, diff --git a/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol b/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol index 2863a3cb..af4db241 100644 --- a/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol +++ b/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol @@ -98,15 +98,6 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { return _baseVariableBorrowRate.add(_variableRateSlope1).add(_variableRateSlope2); } - struct CalcInterestRatesLocalVars { - uint256 totalDebt; - uint256 currentVariableBorrowRate; - uint256 currentStableBorrowRate; - uint256 currentLiquidityRate; - uint256 utilizationRate; - uint256 availableLiquidity; - } - /** * @dev Calculates the interest rates depending on the reserve's state and configurations * @param reserve The address of the reserve @@ -136,6 +127,58 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { uint256, uint256 ) + { + uint256 availableLiquidity = IERC20(reserve).balanceOf(aToken); + //avoid stack too deep + availableLiquidity = availableLiquidity.add(liquidityAdded).sub(liquidityTaken); + + return + calculateInterestRates( + reserve, + availableLiquidity, + totalStableDebt, + totalVariableDebt, + averageStableBorrowRate, + reserveFactor + ); + } + + struct CalcInterestRatesLocalVars { + uint256 totalDebt; + uint256 currentVariableBorrowRate; + uint256 currentStableBorrowRate; + uint256 currentLiquidityRate; + uint256 utilizationRate; + } + + /** + * @dev Calculates the interest rates depending on the reserve's state and configurations. + * NOTE This function is kept for compatibility with the previous DefaultInterestRateStrategy interface. + * New protocol implementation uses the new calculateInterestRates() interface + * @param reserve The address of the reserve + * @param availableLiquidity The liquidity available in the corresponding aToken + * @param totalStableDebt The total borrowed from the reserve a stable rate + * @param totalVariableDebt The total borrowed from the reserve at a variable rate + * @param averageStableBorrowRate The weighted average of all the stable rate loans + * @param reserveFactor The reserve portion of the interest that goes to the treasury of the market + * @return The liquidity rate, the stable borrow rate and the variable borrow rate + **/ + function calculateInterestRates( + address reserve, + uint256 availableLiquidity, + uint256 totalStableDebt, + uint256 totalVariableDebt, + uint256 averageStableBorrowRate, + uint256 reserveFactor + ) + public + view + override + returns ( + uint256, + uint256, + uint256 + ) { CalcInterestRatesLocalVars memory vars; @@ -143,11 +186,10 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { vars.currentVariableBorrowRate = 0; vars.currentStableBorrowRate = 0; vars.currentLiquidityRate = 0; - vars.availableLiquidity = IERC20(reserve).balanceOf(aToken); - vars.availableLiquidity = vars.availableLiquidity.add(liquidityAdded).sub(liquidityTaken); - vars.utilizationRate = - vars.totalDebt == 0 ? 0 : vars.totalDebt.rayDiv(vars.availableLiquidity.add(vars.totalDebt)); + vars.utilizationRate = vars.totalDebt == 0 + ? 0 + : vars.totalDebt.rayDiv(availableLiquidity.add(vars.totalDebt)); vars.currentStableBorrowRate = ILendingRateOracle(addressesProvider.getLendingRateOracle()) .getMarketBorrowRate(reserve); diff --git a/test-suites/test-aave/rate-strategy.spec.ts b/test-suites/test-aave/rate-strategy.spec.ts index 83021e97..6961f8b5 100644 --- a/test-suites/test-aave/rate-strategy.spec.ts +++ b/test-suites/test-aave/rate-strategy.spec.ts @@ -42,7 +42,7 @@ makeSuite('Interest rate strategy tests', (testEnv: TestEnv) => { 0: currentLiquidityRate, 1: currentStableBorrowRate, 2: currentVariableBorrowRate, - } = await strategyInstance.calculateInterestRates( + } = await strategyInstance['calculateInterestRates(address,address,uint256,uint256,uint256,uint256,uint256,uint256)']( dai.address, aDai.address, 0, @@ -69,7 +69,7 @@ makeSuite('Interest rate strategy tests', (testEnv: TestEnv) => { 0: currentLiquidityRate, 1: currentStableBorrowRate, 2: currentVariableBorrowRate, - } = await strategyInstance.calculateInterestRates( + } = await strategyInstance['calculateInterestRates(address,address,uint256,uint256,uint256,uint256,uint256,uint256)']( dai.address, aDai.address, '200000000000000000', @@ -108,7 +108,7 @@ makeSuite('Interest rate strategy tests', (testEnv: TestEnv) => { 0: currentLiquidityRate, 1: currentStableBorrowRate, 2: currentVariableBorrowRate, - } = await strategyInstance.calculateInterestRates( + } = await strategyInstance['calculateInterestRates(address,address,uint256,uint256,uint256,uint256,uint256,uint256)']( dai.address, aDai.address, '0', @@ -150,7 +150,7 @@ makeSuite('Interest rate strategy tests', (testEnv: TestEnv) => { 0: currentLiquidityRate, 1: currentStableBorrowRate, 2: currentVariableBorrowRate, - } = await strategyInstance.calculateInterestRates( + } = await strategyInstance['calculateInterestRates(address,address,uint256,uint256,uint256,uint256,uint256,uint256)']( dai.address, aDai.address, '0', From 671a6878bfc61d6b5b33a063ea3276d1405213c7 Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 10 Mar 2021 18:17:52 +0100 Subject: [PATCH 173/219] Update LP oracles with latest oracle interface --- hardhat.config.ts | 2 +- markets/amm/commons.ts | 64 +++++++++++++++++++++--------------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 0c6fa1e1..234be8f2 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -58,7 +58,7 @@ const getCommonNetworkConfig = (networkName: eNetwork, networkId: number) => ({ const mainnetFork = MAINNET_FORK ? { - blockNumber: 11739065, + blockNumber: 12012081, url: NETWORKS_RPC_URL['main'], } : undefined; diff --git a/markets/amm/commons.ts b/markets/amm/commons.ts index b892064d..3a676eda 100644 --- a/markets/amm/commons.ts +++ b/markets/amm/commons.ts @@ -253,22 +253,22 @@ export const CommonsConfig: ICommonConfiguration = { WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', - UniDAIWETH: '0xf4071801C4421Db7e63DaC15B9432e50C44a7F42', - UniWBTCWETH: '0x55EF7F1226507cFd846DE009C2f097c2211b6Fb8', - UniAAVEWETH: '0x5671387d56eAB334A2D65d6D0BB4D907898C7abA', - UniBATWETH: '0xA61ca04DF33B72b235a8A28CfB535bb7A5271B70', - UniDAIUSDC: '0xFd8dFc92B030e6BA957336e9f08C2a711e19069A', - UniCRVWETH: '0xd4D344D076256Fdf806375983b2cab2Db52FD506', - UniLINKWETH: '0x8C0e5df19B998F06e57A1Db1a38232F7590abe4b', - UniMKRWETH: '0x92f2A28fE33E0b6Ea218057EEe004E3B2B6de45d', - UniRENWETH: '0xFc0398b247107138dB494395600fB0d075b72C9A', - UniSNXWETH: '0xF5CB13c859383B5fb070bd111Cae7a900c00BA07', - UniUNIWETH: '0xE50e47E37DCF55dE1c5F2c32d346BB52064f7CE6', - UniUSDCWETH: '0xBE6ac123799572c98eFdE48895465AB392534AFD', - UniWBTCUSDC: '0xd6b8b08a0d13994A5f4a1949F4870DE57e9B40d9', - UniYFIWETH: '0x94daB35789f05f54224F6851921160DE21318072', - BptWBTCWETH: '0x4a2731c9f3B4355922c676f9b538278D79C299C5', - BptBALWETH: '0xD9400999f38E1877a6dDDb0090A327F19257f9AE', + UniDAIWETH: '0x66a6b87a18db78086acda75b7720dc47cdabcc05', + UniWBTCWETH: '0x7004BB6F2013F13C54899309cCa029B49707E547', + UniAAVEWETH: '0xB525547968610395B60085bDc8033FFeaEaa5F64', + UniBATWETH: '0xB394D8a1CE721630Cbea8Ec110DCEf0D283EDE3a', + UniDAIUSDC: '0x3B148Fa5E8297DB64262442052b227328730EA81', + UniCRVWETH: '0x10F7078e2f29802D2AC78045F61A69aE0883535A', + UniLINKWETH: '0x30adCEfA5d483284FD79E1eFd54ED3e0A8eaA632', + UniMKRWETH: '0xEBF4A448ff3D835F8FA883941a3E9D5E74B40B5E', + UniRENWETH: '0xe2f7C06906A9dB063C28EB5c71B6Ab454e5222dD', + UniSNXWETH: '0x29bfee7E90572Abf1088a58a145a10D051b78E46', + UniUNIWETH: '0xC2E93e8121237A885A00627975eB06C7BF9808d6', + UniUSDCWETH: '0x71c4a2173CE3620982DC8A7D870297533360Da4E', + UniWBTCUSDC: '0x11f4ba2227F21Dc2A9F0b0e6Ea740369d580a212', + UniYFIWETH: '0x664223b8Bb0934aE0970e601F452f75AaCe9Aa2A', + BptWBTCWETH: '0x4CA8D8fC2b4fCe8A2dcB71Da884bba042d48E067', + BptBALWETH: '0x2e4e78936b100be6Ef85BCEf7FB25bC770B02B85', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, [eEthereumNetwork.tenderlyMain]: { @@ -276,22 +276,22 @@ export const CommonsConfig: ICommonConfiguration = { WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8', USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4', DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4', - UniDAIWETH: '0xf4071801C4421Db7e63DaC15B9432e50C44a7F42', - UniWBTCWETH: '0x55EF7F1226507cFd846DE009C2f097c2211b6Fb8', - UniAAVEWETH: '0x5671387d56eAB334A2D65d6D0BB4D907898C7abA', - UniBATWETH: '0xA61ca04DF33B72b235a8A28CfB535bb7A5271B70', - UniDAIUSDC: '0xFd8dFc92B030e6BA957336e9f08C2a711e19069A', - UniCRVWETH: '0xd4D344D076256Fdf806375983b2cab2Db52FD506', - UniLINKWETH: '0x8C0e5df19B998F06e57A1Db1a38232F7590abe4b', - UniMKRWETH: '0x92f2A28fE33E0b6Ea218057EEe004E3B2B6de45d', - UniRENWETH: '0xFc0398b247107138dB494395600fB0d075b72C9A', - UniSNXWETH: '0xF5CB13c859383B5fb070bd111Cae7a900c00BA07', - UniUNIWETH: '0xE50e47E37DCF55dE1c5F2c32d346BB52064f7CE6', - UniUSDCWETH: '0xBE6ac123799572c98eFdE48895465AB392534AFD', - UniWBTCUSDC: '0xd6b8b08a0d13994A5f4a1949F4870DE57e9B40d9', - UniYFIWETH: '0x94daB35789f05f54224F6851921160DE21318072', - BptWBTCWETH: '0x4a2731c9f3B4355922c676f9b538278D79C299C5', - BptBALWETH: '0xD9400999f38E1877a6dDDb0090A327F19257f9AE', + UniDAIWETH: '0x66a6b87a18db78086acda75b7720dc47cdabcc05', + UniWBTCWETH: '0x7004BB6F2013F13C54899309cCa029B49707E547', + UniAAVEWETH: '0xB525547968610395B60085bDc8033FFeaEaa5F64', + UniBATWETH: '0xB394D8a1CE721630Cbea8Ec110DCEf0D283EDE3a', + UniDAIUSDC: '0x3B148Fa5E8297DB64262442052b227328730EA81', + UniCRVWETH: '0x10F7078e2f29802D2AC78045F61A69aE0883535A', + UniLINKWETH: '0x30adCEfA5d483284FD79E1eFd54ED3e0A8eaA632', + UniMKRWETH: '0xEBF4A448ff3D835F8FA883941a3E9D5E74B40B5E', + UniRENWETH: '0xe2f7C06906A9dB063C28EB5c71B6Ab454e5222dD', + UniSNXWETH: '0x29bfee7E90572Abf1088a58a145a10D051b78E46', + UniUNIWETH: '0xC2E93e8121237A885A00627975eB06C7BF9808d6', + UniUSDCWETH: '0x71c4a2173CE3620982DC8A7D870297533360Da4E', + UniWBTCUSDC: '0x11f4ba2227F21Dc2A9F0b0e6Ea740369d580a212', + UniYFIWETH: '0x664223b8Bb0934aE0970e601F452f75AaCe9Aa2A', + BptWBTCWETH: '0x4CA8D8fC2b4fCe8A2dcB71Da884bba042d48E067', + BptBALWETH: '0x2e4e78936b100be6Ef85BCEf7FB25bC770B02B85', USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', }, }, From b7aed31f79e17a1cffc1e9f26cd97a963a2bbfbf Mon Sep 17 00:00:00 2001 From: Pierrick Turelier Date: Mon, 15 Mar 2021 21:42:33 +0100 Subject: [PATCH 174/219] feat(IAToken): add UNDERLYING_ASSET_ADDRESS function --- contracts/interfaces/IAToken.sol | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contracts/interfaces/IAToken.sol b/contracts/interfaces/IAToken.sol index 3a6ac663..cf0ea261 100644 --- a/contracts/interfaces/IAToken.sol +++ b/contracts/interfaces/IAToken.sol @@ -99,4 +99,9 @@ interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken { * @dev Returns the address of the incentives controller contract **/ function getIncentivesController() external view returns (IAaveIncentivesController); + + /** + * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) + **/ + function UNDERLYING_ASSET_ADDRESS() external view returns (address); } From 44f8b40c75c2c7adf3a24bb41c6fcd99f1599fb7 Mon Sep 17 00:00:00 2001 From: l3lackcurtains Date: Tue, 16 Mar 2021 14:52:40 -0700 Subject: [PATCH 175/219] Fix two scripts in package.json --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 4532f6fa..7076c576 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "hardhat": "hardhat", "hardhat:kovan": "hardhat --network kovan", "hardhat:tenderly-main": "hardhat --network tenderlyMain", - "hardhat:ropsten": "hardhat--network ropsten", + "hardhat:ropsten": "hardhat --network ropsten", "hardhat:main": "hardhat --network main", "hardhat:docker": "hardhat --network hardhatevm_docker", "hardhat:mumbai": "hardhat --network mumbai", @@ -60,7 +60,7 @@ "ci:clean": "rm -rf ./artifacts ./cache ./types", "print-contracts:kovan": "npm run hardhat:kovan -- print-contracts", "print-contracts:main": "npm run hardhat:main -- print-contracts", - "print-contracts:ropsten": "npm run hardhat:main -- print-contracts", + "print-contracts:ropsten": "npm run hardhat:ropsten -- print-contracts", "dev:deployUIProvider": "npm run hardhat:kovan deploy-UiPoolDataProvider", "dev:deployUniswapRepayAdapter": "hardhat --network kovan deploy-UniswapRepayAdapter --provider 0x88757f2f99175387aB4C6a4b3067c77A695b0349 --router 0xfcd87315f0e4067070ade8682fcdbc3006631441 --weth 0xd0a1e359811322d97991e03f863a0c30c2cf029c", "dev:UniswapLiquiditySwapAdapter": "hardhat --network kovan deploy-UniswapLiquiditySwapAdapter --provider 0x88757f2f99175387aB4C6a4b3067c77A695b0349 --router 0xfcd87315f0e4067070ade8682fcdbc3006631441 --weth 0xd0a1e359811322d97991e03f863a0c30c2cf029c", @@ -153,4 +153,4 @@ "ethereum", "solidity" ] -} +} \ No newline at end of file From 7777d1d5cfd71a97d2308edca58ae6199d6dfb48 Mon Sep 17 00:00:00 2001 From: l3lackcurtains Date: Tue, 16 Mar 2021 14:57:58 -0700 Subject: [PATCH 176/219] replace with Add flag for verify on aave.dev.ts --- tasks/migrations/aave.dev.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/migrations/aave.dev.ts b/tasks/migrations/aave.dev.ts index 842d1861..16ff3a6a 100644 --- a/tasks/migrations/aave.dev.ts +++ b/tasks/migrations/aave.dev.ts @@ -4,7 +4,7 @@ import { ConfigNames } from '../../helpers/configuration'; import { printContracts } from '../../helpers/misc-utils'; task('aave:dev', 'Deploy development enviroment') - .addOptionalParam('verify', 'Verify contracts at Etherscan') + .addFlag('verify', 'Verify contracts at Etherscan') .setAction(async ({ verify }, localBRE) => { const POOL_NAME = ConfigNames.Aave; From 16b7a096efec396b3a626cfb600ce179f7eb330a Mon Sep 17 00:00:00 2001 From: David Racero Date: Mon, 22 Mar 2021 14:09:26 +0100 Subject: [PATCH 177/219] Fix npm i install due old package-lock --- package-lock.json | 3953 ++++++++++++++++----------------------------- 1 file changed, 1424 insertions(+), 2529 deletions(-) diff --git a/package-lock.json b/package-lock.json index 80fbb840..b05b76cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,27 +5,27 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", "dev": true, "requires": { - "@babel/highlight": "^7.10.4" + "@babel/highlight": "^7.12.13" } }, "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", "dev": true }, "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.12.11", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } @@ -180,9 +180,9 @@ } }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", "dev": true }, "yargs": { @@ -226,35 +226,61 @@ "dev": true }, "@ethereum-waffle/chai": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/chai/-/chai-3.2.0.tgz", - "integrity": "sha512-3mvI7luX8FSAX2yjklSN8rw8F8RNaMzZDadDkS9JvmoM4khByGe3mDn8rVroneBAcFusXJfL6BEssGj5S4mD7Q==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/chai/-/chai-3.3.1.tgz", + "integrity": "sha512-+vepCjttfOzCSnmiVEmd1bR8ctA2wYVrtWa8bDLhnTpj91BIIHotNDTwpeq7fyjrOCIBTN3Ai8ACfjNoatc4OA==", "dev": true, "requires": { - "@ethereum-waffle/provider": "^3.2.0", + "@ethereum-waffle/provider": "^3.3.1", "ethers": "^5.0.0" } }, "@ethereum-waffle/compiler": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/compiler/-/compiler-3.2.0.tgz", - "integrity": "sha512-Tg8YjbcVKQkNwhbiBf9Z4kKPolPO0IB+iYwAdpXNwgyMOH74guIHhFGtKOCPoY4VXR75erGgeQIt2PzIn/szCA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/compiler/-/compiler-3.3.1.tgz", + "integrity": "sha512-X/TeQugt94AQwXEdCjIQxcXYGawNulVBYEBE7nloj4wE/RBxNolXwjoVNjcS4kuiMMbKkdO0JkL5sn6ixx8bDg==", "dev": true, "requires": { "@resolver-engine/imports": "^0.3.3", "@resolver-engine/imports-fs": "^0.3.3", + "@typechain/ethers-v5": "^2.0.0", "@types/mkdirp": "^0.5.2", "@types/node-fetch": "^2.5.5", "ethers": "^5.0.1", "mkdirp": "^0.5.1", "node-fetch": "^2.6.0", - "solc": "^0.6.3" + "solc": "^0.6.3", + "ts-generator": "^0.1.1", + "typechain": "^3.0.0" + }, + "dependencies": { + "ts-essentials": { + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-6.0.7.tgz", + "integrity": "sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw==", + "dev": true + }, + "typechain": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-3.0.0.tgz", + "integrity": "sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg==", + "dev": true, + "requires": { + "command-line-args": "^4.0.7", + "debug": "^4.1.1", + "fs-extra": "^7.0.0", + "js-sha3": "^0.8.0", + "lodash": "^4.17.15", + "ts-essentials": "^6.0.3", + "ts-generator": "^0.1.1" + } + } } }, "@ethereum-waffle/ens": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/ens/-/ens-3.2.0.tgz", - "integrity": "sha512-n4EYJDLAwN2X+2EsZMasXRlz5gYp39Tmy18RU4f6ZdnTNuVNw1BNkCC9VzrQooHGvHLjKZFPvcl+FRfBO+Xcyw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/ens/-/ens-3.2.3.tgz", + "integrity": "sha512-OIfguJu4e+NYJHNnNVaFzvNG5WYPntWU1vnQuAFszBFytOeIkv2hAXv8RmRL+cledcvShtP3gmXU3Lvf0o4Sxw==", "dev": true, "requires": { "@ensdomains/ens": "^0.4.4", @@ -263,9 +289,9 @@ } }, "@ethereum-waffle/mock-contract": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/mock-contract/-/mock-contract-3.2.0.tgz", - "integrity": "sha512-TfBt9ka2DXVxxIBee3WB0gSLgWCo9ZegqcdXjCz0QGlu+dEhL8W3+aLDYQoyx3kwlecfNl8EQ1V7g7GH8wrlMg==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/mock-contract/-/mock-contract-3.2.2.tgz", + "integrity": "sha512-H60Cc5C7sYNU4LuPMSKDh8YIaN9/fkwEjznY78CEbOosO+lMlFYdA+5VZjeDGDuYKfsBqsocQdkj1CRyoi1KNw==", "dev": true, "requires": { "@ethersproject/abi": "^5.0.1", @@ -273,12 +299,12 @@ } }, "@ethereum-waffle/provider": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/provider/-/provider-3.2.0.tgz", - "integrity": "sha512-U9KyjMKIZuK4gi2kzWIJkAXYjtg0aIlEQ0F4yKqHMRyqAiSM6M4VJgn6tHisxe3Ev9z/jSnutKT8dyAEwlIYdw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/provider/-/provider-3.3.1.tgz", + "integrity": "sha512-I7iziCqvkVhfaYKRRjUoEK3JHne5PffLd8dokI9RvDighKn/OA4P8mMb400EGmuDG5NTVTM5hdnTa2jIYwrhyA==", "dev": true, "requires": { - "@ethereum-waffle/ens": "^3.2.0", + "@ethereum-waffle/ens": "^3.2.2", "ethers": "^5.0.1", "ganache-core": "^2.10.2", "patch-package": "^6.2.2", @@ -286,193 +312,192 @@ } }, "@ethersproject/abi": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz", - "integrity": "sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==", + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.13.tgz", + "integrity": "sha512-2coOH3D7ra1lwamKEH0HVc+Jbcsw5yfeCgmY8ekhCDualEiyyovD2qDcMBBcY3+kjoLHVTmo7ost6MNClxdOrg==", "dev": true, "requires": { - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/strings": "^5.0.4" + "@ethersproject/address": "^5.0.9", + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/constants": "^5.0.8", + "@ethersproject/hash": "^5.0.10", + "@ethersproject/keccak256": "^5.0.7", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/strings": "^5.0.8" } }, "@ethersproject/abstract-provider": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.5.tgz", - "integrity": "sha512-i/CjElAkzV7vQBAeoz+IpjGfcFYEP9eD7j3fzZ0fzTq03DO7PPnR+xkEZ1IoDXGwDS+55aLM1xvLDwB/Lx6IOQ==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.10.tgz", + "integrity": "sha512-OSReY5iz94iIaPlRvLiJP8YVIvQLx4aUvMMnHWSaA/vTU8QHZmgNlt4OBdYV1+aFY8Xl+VRYiWBHq72ZDKXXCQ==", "dev": true, "requires": { - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/networks": "^5.0.3", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/transactions": "^5.0.5", - "@ethersproject/web": "^5.0.6" + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/networks": "^5.0.7", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/transactions": "^5.0.9", + "@ethersproject/web": "^5.0.12" } }, "@ethersproject/abstract-signer": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.7.tgz", - "integrity": "sha512-8W8gy/QutEL60EoMEpvxZ8MFAEWs/JvH5nmZ6xeLXoZvmBCasGmxqHdYjo2cxg0nevkPkq9SeenSsBBZSCx+SQ==", + "version": "5.0.14", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.14.tgz", + "integrity": "sha512-JztBwVO7o5OHLh2vyjordlS4/1EjRyaECtc8vPdXTF1i4dXN+J0coeRoPN6ZFbBvi/YbaB6br2fvqhst1VQD/g==", "dev": true, "requires": { - "@ethersproject/abstract-provider": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3" + "@ethersproject/abstract-provider": "^5.0.8", + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7" } }, "@ethersproject/address": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.5.tgz", - "integrity": "sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.11.tgz", + "integrity": "sha512-Et4GBdD8/tsBGjCEOKee9upN29qjL5kbRcmJifb4Penmiuh9GARXL2/xpXvEp5EW+EIW/rfCHFJrkYBgoQFQBw==", "dev": true, "requires": { - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/rlp": "^5.0.3", - "bn.js": "^4.4.0" + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/keccak256": "^5.0.7", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/rlp": "^5.0.7" } }, "@ethersproject/base64": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.4.tgz", - "integrity": "sha512-4KRykQ7BQMeOXfvio1YITwHjxwBzh92UoXIdzxDE1p53CK28bbHPdsPNYo0wl0El7lJAMpT2SOdL0hhbWRnyIA==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.9.tgz", + "integrity": "sha512-37RBz5LEZ9SlTNGiWCYFttnIN9J7qVs9Xo2EbqGqDH5LfW9EIji66S+YDMpXVo1zWDax1FkEldAoatxHK2gfgA==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.4" + "@ethersproject/bytes": "^5.0.9" } }, "@ethersproject/basex": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.0.4.tgz", - "integrity": "sha512-ixIr/kKiAoSzOnSc777AGIOAhKai5Ivqr4HO/Gz+YG+xkfv6kqD6AW4ga9vM20Wwb0QBhh3LoRWTu4V1K+x9Ew==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.0.9.tgz", + "integrity": "sha512-FANswl1IN3PS0eltQxH2aM2+utPrkLUVG4XVFi6SafRG9EpAqXCgycxC8PU90mPGhigYTpg9cnTB5mCZ6ejQjw==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/properties": "^5.0.3" + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/properties": "^5.0.7" } }, "@ethersproject/bignumber": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.8.tgz", - "integrity": "sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA==", + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.15.tgz", + "integrity": "sha512-MTADqnyacvdRwtKh7o9ujwNDSM1SDJjYDMYAzjIgjoi9rh6TY4suMbhCa3i2vh3SUXiXSICyTI8ui+NPdrZ9Lw==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", "bn.js": "^4.4.0" } }, "@ethersproject/bytes": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.5.tgz", - "integrity": "sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.11.tgz", + "integrity": "sha512-D51plLYY5qF05AsoVQwIZVLqlBkaTPVHVP/1WmmBIWyHB0cRW0C9kh0kx5Exo51rB63Hk8PfHxc7SmpoaQFEyg==", "dev": true, "requires": { - "@ethersproject/logger": "^5.0.5" + "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/constants": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.5.tgz", - "integrity": "sha512-foaQVmxp2+ik9FrLUCtVrLZCj4M3Ibgkqvh+Xw/vFRSerkjVSYePApaVE5essxhoSlF1U9oXfWY09QI2AXtgKA==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.10.tgz", + "integrity": "sha512-OSo8jxkHLDXieCy8bgOFR7lMfgPxEzKvSDdP+WAWHCDM8+orwch0B6wzkTmiQFgryAtIctrBt5glAdJikZ3hGw==", "dev": true, "requires": { - "@ethersproject/bignumber": "^5.0.7" + "@ethersproject/bignumber": "^5.0.13" } }, "@ethersproject/contracts": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.0.5.tgz", - "integrity": "sha512-tFI255lFbmbqMkgnuyhDWHl3yWqttPlReplYuVvDCT/SuvBjLR4ad2uipBlh1fh5X1ipK9ettAoV4S0HKim4Kw==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.0.12.tgz", + "integrity": "sha512-srijy31idjz8bE+gL1I6IRj2H4I9dUwfQ+QroLrIgNdGArqY8y2iFUKa3QTy+JBX26fJsdYiCQi1kKkaNpnMpQ==", "dev": true, "requires": { - "@ethersproject/abi": "^5.0.5", - "@ethersproject/abstract-provider": "^5.0.4", - "@ethersproject/abstract-signer": "^5.0.4", - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3" + "@ethersproject/abi": "^5.0.10", + "@ethersproject/abstract-provider": "^5.0.8", + "@ethersproject/abstract-signer": "^5.0.10", + "@ethersproject/address": "^5.0.9", + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/constants": "^5.0.8", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7" } }, "@ethersproject/hash": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.6.tgz", - "integrity": "sha512-Gvh57v6BWhwnud6l7tMfQm32PRQ2DYx2WaAAQmAxAfYvmzUkpQCBstnGeNMXIL8/2wdkvcB2u+WZRWaZtsFuUQ==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.12.tgz", + "integrity": "sha512-kn4QN+fhNFbUgX3XZTZUaQixi0oyfIEY+hfW+KtkHu+rq7dV76oAIvaLEEynu1/4npOL38E4X4YI42gGZk+C0Q==", "dev": true, "requires": { - "@ethersproject/abstract-signer": "^5.0.6", - "@ethersproject/address": "^5.0.5", - "@ethersproject/bignumber": "^5.0.8", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.4", - "@ethersproject/strings": "^5.0.4" + "@ethersproject/abstract-signer": "^5.0.10", + "@ethersproject/address": "^5.0.9", + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/keccak256": "^5.0.7", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/strings": "^5.0.8" } }, "@ethersproject/hdnode": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.0.5.tgz", - "integrity": "sha512-Ho4HZaK+KijE5adayvjAGusWMnT0mgwGa5hGMBofBOgX9nqiKf6Wxx68SXBGI1/L3rmKo6mlAjxUd8gefs0teQ==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.0.10.tgz", + "integrity": "sha512-ZLwMtIcXK7xz2lSITDCl40W04CtRq4K9NwBxhCzdzPdaz6XnoJMwGz2YMVLg+8ksseq+RYtTwIIXtlK6vyvQyg==", "dev": true, "requires": { - "@ethersproject/abstract-signer": "^5.0.4", - "@ethersproject/basex": "^5.0.3", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/pbkdf2": "^5.0.3", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/sha2": "^5.0.3", - "@ethersproject/signing-key": "^5.0.4", - "@ethersproject/strings": "^5.0.4", - "@ethersproject/transactions": "^5.0.5", - "@ethersproject/wordlists": "^5.0.4" + "@ethersproject/abstract-signer": "^5.0.10", + "@ethersproject/basex": "^5.0.7", + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/pbkdf2": "^5.0.7", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/sha2": "^5.0.7", + "@ethersproject/signing-key": "^5.0.8", + "@ethersproject/strings": "^5.0.8", + "@ethersproject/transactions": "^5.0.9", + "@ethersproject/wordlists": "^5.0.8" } }, "@ethersproject/json-wallets": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.0.7.tgz", - "integrity": "sha512-dgOn9JtGgjT28mDXs4LYY2rT4CzS6bG/rxoYuPq3TLHIf6nmvBcr33Fee6RrM/y8UAx4gyIkf6wb2cXsOctvQQ==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.0.12.tgz", + "integrity": "sha512-nac553zGZnOewpjlqbfy7WBl8m3y7qudzRsI2dCxrediYtPIVIs9f6Pbnou8vDmmp8X4/U4W788d+Ma88o+Gbg==", "dev": true, "requires": { - "@ethersproject/abstract-signer": "^5.0.4", - "@ethersproject/address": "^5.0.4", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/hdnode": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/pbkdf2": "^5.0.3", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/random": "^5.0.3", - "@ethersproject/strings": "^5.0.4", - "@ethersproject/transactions": "^5.0.5", + "@ethersproject/abstract-signer": "^5.0.10", + "@ethersproject/address": "^5.0.9", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/hdnode": "^5.0.8", + "@ethersproject/keccak256": "^5.0.7", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/pbkdf2": "^5.0.7", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/random": "^5.0.7", + "@ethersproject/strings": "^5.0.8", + "@ethersproject/transactions": "^5.0.9", "aes-js": "3.0.0", "scrypt-js": "3.0.1" } }, "@ethersproject/keccak256": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.4.tgz", - "integrity": "sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.9.tgz", + "integrity": "sha512-zhdUTj6RGtCJSgU+bDrWF6cGbvW453LoIC1DSNWrTlXzC7WuH4a+EiPrgc7/kNoRxerKuA/cxYlI8GwNtVtDlw==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.4", + "@ethersproject/bytes": "^5.0.9", "js-sha3": "0.5.7" }, "dependencies": { @@ -485,62 +510,62 @@ } }, "@ethersproject/logger": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.6.tgz", - "integrity": "sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.10.tgz", + "integrity": "sha512-0y2T2NqykDrbPM3Zw9RSbPkDOxwChAL8detXaom76CfYoGxsOnRP/zTX8OUAV+x9LdwzgbWvWmeXrc0M7SuDZw==", "dev": true }, "@ethersproject/networks": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.4.tgz", - "integrity": "sha512-/wHDTRms5mpJ09BoDrbNdFWINzONe05wZRgohCXvEv39rrH/Gd/yAnct8wC0RsW3tmFOgjgQxuBvypIxuUynTw==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.9.tgz", + "integrity": "sha512-L8+VCQwArBLGkxZb/5Ns/OH/OxP38AcaveXIxhUTq+VWpXYjrObG3E7RDQIKkUx1S1IcQl/UWTz5w4DK0UitJg==", "dev": true, "requires": { - "@ethersproject/logger": "^5.0.5" + "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/pbkdf2": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.0.4.tgz", - "integrity": "sha512-9jVBjHXQKfr9+3bkCg01a8Cd1H9e+7Kw3ZMIvAxD0lZtuzrXsJxm1hVwY9KA+PRUvgS/9tTP4viXQYwLAax7zg==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.0.9.tgz", + "integrity": "sha512-ItE/wQ/WVw/ajEHPUVgfu0aEvksPgOQc+278bke8sGKnGO3ppjmqp0MHh17tHc1EBTzJbSms5aLIqc56qZ/oiA==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/sha2": "^5.0.3" + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/sha2": "^5.0.7" } }, "@ethersproject/properties": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.4.tgz", - "integrity": "sha512-UdyX3GqBxFt15B0uSESdDNmhvEbK3ACdDXl2soshoPcneXuTswHDeA0LoPlnaZzhbgk4p6jqb4GMms5C26Qu6A==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.9.tgz", + "integrity": "sha512-ZCjzbHYTw+rF1Pn8FDCEmx3gQttwIHcm/6Xee8g/M3Ga3SfW4tccNMbs5zqnBH0E4RoOPaeNgyg1O68TaF0tlg==", "dev": true, "requires": { - "@ethersproject/logger": "^5.0.5" + "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/providers": { - "version": "5.0.14", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.0.14.tgz", - "integrity": "sha512-K9QRRkkHWyprm3g4L8U9aPx5uyivznL4RYemkN2shCQumyGqFJ5SO+OtQrgebVm0JpGwFAUGugnhRUh49sjErw==", + "version": "5.0.24", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.0.24.tgz", + "integrity": "sha512-M4Iw1r4gGJkt7ZUa++iREuviKL/DIpmIMsaUlVlXtV+ZrUXeN8xQ3zOTrbz7R4h9W9oljBZM7i4D3Kn1krJ30A==", "dev": true, "requires": { - "@ethersproject/abstract-provider": "^5.0.4", - "@ethersproject/abstract-signer": "^5.0.4", - "@ethersproject/address": "^5.0.4", - "@ethersproject/basex": "^5.0.3", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/networks": "^5.0.3", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/random": "^5.0.3", - "@ethersproject/rlp": "^5.0.3", - "@ethersproject/sha2": "^5.0.3", - "@ethersproject/strings": "^5.0.4", - "@ethersproject/transactions": "^5.0.5", - "@ethersproject/web": "^5.0.6", + "@ethersproject/abstract-provider": "^5.0.8", + "@ethersproject/abstract-signer": "^5.0.10", + "@ethersproject/address": "^5.0.9", + "@ethersproject/basex": "^5.0.7", + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/constants": "^5.0.8", + "@ethersproject/hash": "^5.0.10", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/networks": "^5.0.7", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/random": "^5.0.7", + "@ethersproject/rlp": "^5.0.7", + "@ethersproject/sha2": "^5.0.7", + "@ethersproject/strings": "^5.0.8", + "@ethersproject/transactions": "^5.0.9", + "@ethersproject/web": "^5.0.12", "bech32": "1.1.4", "ws": "7.2.3" }, @@ -554,33 +579,33 @@ } }, "@ethersproject/random": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.0.4.tgz", - "integrity": "sha512-AIZJhqs6Ba4/+U3lOjt3QZbP6b/kuuGLJUYFUonAgWmkTHwqsCwYnFvnHKQSUuHbXHvErp7WFXFlztx+yMn3kQ==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.0.9.tgz", + "integrity": "sha512-DANG8THsKqFbJOantrxumtG6gyETNE54VfbsWa+SQAT8WKpDo9W/X5Zhh73KuhClaey1UI32uVmISZeq/Zxn1A==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5" + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/rlp": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.4.tgz", - "integrity": "sha512-5qrrZad7VTjofxSsm7Zg/7Dr4ZOln4S2CqiDdOuTv6MBKnXj0CiBojXyuDy52M8O3wxH0CyE924hXWTDV1PQWQ==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.9.tgz", + "integrity": "sha512-ns1U7ZMVeruUW6JXc4om+1w3w4ynHN/0fpwmeNTsAjwGKoF8SAUgue6ylKpHKWSti2idx7jDxbn8hNNFHk67CA==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5" + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/sha2": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.0.4.tgz", - "integrity": "sha512-0yFhf1mspxAfWdXXoPtK94adUeu1R7/FzAa+DfEiZTc76sz/vHXf0LSIazoR3znYKFny6haBxME+usbvvEcF3A==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.0.9.tgz", + "integrity": "sha512-5FH4s47gM7N1fFAYQ1+m7aX0SbLg0Xr+6tvqndmNqc382/qBIbzXiGlUookrsjlPb6gLNurnTssCXjNM72J6lQ==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", "hash.js": "1.1.3" }, "dependencies": { @@ -597,141 +622,141 @@ } }, "@ethersproject/signing-key": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.5.tgz", - "integrity": "sha512-Z1wY7JC1HVO4CvQWY2TyTTuAr8xK3bJijZw1a9G92JEmKdv1j255R/0YLBBcFTl2J65LUjtXynNJ2GbArPGi5g==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.11.tgz", + "integrity": "sha512-Jfcru/BGwdkXhLxT+8WCZtFy7LL0TPFZw05FAb5asxB/MyVsEfNdNxGDtjVE9zXfmRSPe/EusXYY4K7wcygOyQ==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "elliptic": "6.5.3" + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7", + "elliptic": "6.5.4" } }, "@ethersproject/solidity": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.0.5.tgz", - "integrity": "sha512-DMFQ0ouXmNVoKWbGEUFGi8Urli4SJip9jXafQyFHWPRr5oJUqDVkNfwcyC37k+mhBG93k7qrYXCH2xJnGEOxHg==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.0.10.tgz", + "integrity": "sha512-8OG3HLqynWXDA6mVIHuHfF/ojTTwBahON7hc9GAKCqglzXCkVA3OpyxOJXPzjHClRIAUUiU7r9oy9Z/nsjtT/g==", "dev": true, "requires": { - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/sha2": "^5.0.3", - "@ethersproject/strings": "^5.0.4" + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/keccak256": "^5.0.7", + "@ethersproject/sha2": "^5.0.7", + "@ethersproject/strings": "^5.0.8" } }, "@ethersproject/strings": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.5.tgz", - "integrity": "sha512-JED6WaIV00xM/gvj8vSnd+0VWtDYdidTmavFRCTQakqfz+4tDo6Jz5LHgG+dd45h7ah7ykCHW0C7ZXWEDROCXQ==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.10.tgz", + "integrity": "sha512-KAeoS1tZ9/5ECXiIZA6S6hywbD0so2VmuW+Wfyo5EDXeyZ6Na1nxTPhTnW7voQmjbeYJffCrOc0qLFJeylyg7w==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/logger": "^5.0.5" + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/constants": "^5.0.8", + "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/transactions": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.6.tgz", - "integrity": "sha512-htsFhOD+NMBxx676A8ehSuwVV49iqpSB+CkjPZ02tpNew0K6p8g0CZ46Z1ZP946gIHAU80xQ0NACHYrjIUaCFA==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.11.tgz", + "integrity": "sha512-ftsRvR9+gQp7L63F6+XmstvsZ4w8GtWvQB08e/zB+oB86Fnhq8+i/tkgpJplSHC8I/qgiCisva+M3u2GVhDFPA==", "dev": true, "requires": { - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/rlp": "^5.0.3", - "@ethersproject/signing-key": "^5.0.4" + "@ethersproject/address": "^5.0.9", + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/constants": "^5.0.8", + "@ethersproject/keccak256": "^5.0.7", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/rlp": "^5.0.7", + "@ethersproject/signing-key": "^5.0.8" } }, "@ethersproject/units": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.0.6.tgz", - "integrity": "sha512-tsJuy4mipppdmooukRfhXt8fGx9nxvfvG6Xdy0RDm7LzHsjghjwQ69m2bCpId6SDSR1Uq1cQ9irPiUBSyWolUA==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.0.11.tgz", + "integrity": "sha512-nOSPmcCWyB/dwoBRhhTtPGCsTbiXqmc7Q0Adwvafc432AC7hy3Fj3IFZtnSXsbtJ/GdHCIUIoA8gtvxSsFuBJg==", "dev": true, "requires": { - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/logger": "^5.0.5" + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/constants": "^5.0.8", + "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/wallet": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.0.7.tgz", - "integrity": "sha512-n2GX1+2Tc0qV8dguUcLkjNugINKvZY7u/5fEsn0skW9rz5+jHTR5IKMV6jSfXA+WjQT8UCNMvkI3CNcdhaPbTQ==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.0.12.tgz", + "integrity": "sha512-rboJebGf47/KPZrKZQdYg9BAYuXbc/OwcUyML1K1f2jnJeo1ObWV11U1PAWTjTbhhSy6/Fg+34GO2yMb5Dt1Rw==", "dev": true, "requires": { - "@ethersproject/abstract-provider": "^5.0.4", - "@ethersproject/abstract-signer": "^5.0.4", - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/hdnode": "^5.0.4", - "@ethersproject/json-wallets": "^5.0.6", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/random": "^5.0.3", - "@ethersproject/signing-key": "^5.0.4", - "@ethersproject/transactions": "^5.0.5", - "@ethersproject/wordlists": "^5.0.4" + "@ethersproject/abstract-provider": "^5.0.8", + "@ethersproject/abstract-signer": "^5.0.10", + "@ethersproject/address": "^5.0.9", + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/hash": "^5.0.10", + "@ethersproject/hdnode": "^5.0.8", + "@ethersproject/json-wallets": "^5.0.10", + "@ethersproject/keccak256": "^5.0.7", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/random": "^5.0.7", + "@ethersproject/signing-key": "^5.0.8", + "@ethersproject/transactions": "^5.0.9", + "@ethersproject/wordlists": "^5.0.8" } }, "@ethersproject/web": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.9.tgz", - "integrity": "sha512-//QNlv1MSkOII1hv3+HQwWoiVFS+BMVGI0KYeUww4cyrEktnx1QIez5bTSab9s9fWTFaWKNmQNBwMbxAqPuYDw==", + "version": "5.0.14", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.14.tgz", + "integrity": "sha512-QpTgplslwZ0Sp9oKNLoRuS6TKxnkwfaEk3gr7zd7XLF8XBsYejsrQO/03fNfnMx/TAT/RR6WEw/mbOwpRSeVRA==", "dev": true, "requires": { - "@ethersproject/base64": "^5.0.3", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/strings": "^5.0.4" + "@ethersproject/base64": "^5.0.7", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/strings": "^5.0.8" } }, "@ethersproject/wordlists": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.0.5.tgz", - "integrity": "sha512-XA3ycFltVrCTQt04w5nHu3Xq5Z6HjqWsXaAYQHFdqtugyUsIumaO9S5MOwFFuUYTNkZUoT3jCRa/OBS+K4tLfA==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.0.10.tgz", + "integrity": "sha512-jWsEm1iJzpg9SCXnNfFz+tcp4Ofzv0TJb6mj+soCNcar9GcT0yGz62ZsHC3pLQWaF4LkCzGwRJHJTXKjHQfG1A==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/strings": "^5.0.4" + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/hash": "^5.0.10", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/strings": "^5.0.8" } }, "@nodelib/fs.scandir": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", - "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", "dev": true, "requires": { - "@nodelib/fs.stat": "2.0.3", + "@nodelib/fs.stat": "2.0.4", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", "dev": true }, "@nodelib/fs.walk": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", - "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", "dev": true, "requires": { - "@nodelib/fs.scandir": "2.1.3", + "@nodelib/fs.scandir": "2.1.4", "fastq": "^1.6.0" } }, @@ -834,9 +859,9 @@ } }, "@nomiclabs/ethereumjs-vm": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@nomiclabs/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz", - "integrity": "sha512-+XwqoO941bILTO4KDLIUJ37U42ySxw6it7jyoi0tKv0/VUcOrWKF1TCQWMv6dBDRlxpPQd273n9o5SVlYYLRWQ==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@nomiclabs/ethereumjs-vm/-/ethereumjs-vm-4.2.2.tgz", + "integrity": "sha512-8WmX94mMcJaZ7/m7yBbyuS6B+wuOul+eF+RY9fBpGhNaUpyMR/vFIcDojqcWQ4Yafe1tMKY5LDu2yfT4NZgV4Q==", "dev": true, "requires": { "async": "^2.1.2", @@ -850,7 +875,7 @@ "ethereumjs-util": "^6.2.0", "fake-merkle-patricia-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1", - "merkle-patricia-tree": "^2.3.2", + "merkle-patricia-tree": "3.0.0", "rustbn.js": "~0.2.0", "safe-buffer": "^5.1.1", "util.promisify": "^1.0.0" @@ -870,104 +895,19 @@ "ethjs-util": "0.1.6", "rlp": "^2.2.3" } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "merkle-patricia-tree": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", - "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", - "dev": true, - "requires": { - "async": "^1.4.2", - "ethereumjs-util": "^5.0.0", - "level-ws": "0.0.0", - "levelup": "^1.2.1", - "memdown": "^1.0.0", - "readable-stream": "^2.0.0", - "rlp": "^2.0.0", - "semaphore": ">=1.0.1" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "requires": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } } } }, "@nomiclabs/hardhat-ethers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.0.tgz", - "integrity": "sha512-fIi6XP9PgKqwSNVcLDr6S5hvGlc21PendaLD5eGdXEXc9aYQ0OJX8Mk3evs+p78x7W9n9U3ZcKtTiGc1+YScDw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.2.tgz", + "integrity": "sha512-6quxWe8wwS4X5v3Au8q1jOvXYEPkS1Fh+cME5u6AwNdnI4uERvPlVjlgRWzpnb+Rrt1l/cEqiNRH9GlsBMSDQg==", "dev": true }, "@nomiclabs/hardhat-waffle": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.0.tgz", - "integrity": "sha512-CnG9JC0rgqa68LTgyETxBUEWYAovvNGVs5abqaXjG80eF7iMLjDjM8IjOM87siAaxaxFCf6VBMJmtueqVq7jZw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.1.tgz", + "integrity": "sha512-2YR2V5zTiztSH9n8BYWgtv3Q+EL0N5Ltm1PAr5z20uAY4SkkfylJ98CIqt18XFvxTD5x4K2wKBzddjV9ViDAZQ==", "dev": true, "requires": { "@types/sinon-chai": "^3.2.3", @@ -992,9 +932,9 @@ }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -1013,9 +953,9 @@ }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -1037,9 +977,9 @@ }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -1059,9 +999,9 @@ }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -1070,51 +1010,51 @@ } }, "@sentry/core": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.27.4.tgz", - "integrity": "sha512-IbI37cIZU/qBQouuUXaLbGF/9xYFp5STqmj1Gv64l0IZe4JnEp06V3yD5GxQ/mJ78vSfOqfwLooVCUw9FA61sQ==", + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", + "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", "dev": true, "requires": { - "@sentry/hub": "5.27.4", - "@sentry/minimal": "5.27.4", - "@sentry/types": "5.27.4", - "@sentry/utils": "5.27.4", + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", "tslib": "^1.9.3" } }, "@sentry/hub": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.27.4.tgz", - "integrity": "sha512-Ba1AqcjvSd2S+fpdXtXCrVXdrzq9E2Etb2eHUOkEYwSsq7StMOw7E8YHDPAo+to8zUbpMPz/Z9XGhFkyAbImGQ==", + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", + "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", "dev": true, "requires": { - "@sentry/types": "5.27.4", - "@sentry/utils": "5.27.4", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", "tslib": "^1.9.3" } }, "@sentry/minimal": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.27.4.tgz", - "integrity": "sha512-biw5YfIQwvDoaRhLarfeRQ6MJ9UJOoDTmu8Kgg18prJy4rtfDowNJP0OBs5XAsTk6SWAXiE3g7vqUJBXgs7BWA==", + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", + "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", "dev": true, "requires": { - "@sentry/hub": "5.27.4", - "@sentry/types": "5.27.4", + "@sentry/hub": "5.30.0", + "@sentry/types": "5.30.0", "tslib": "^1.9.3" } }, "@sentry/node": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.27.4.tgz", - "integrity": "sha512-fv3FfQ6FiNV56LKk6t48oNw8qgf7X5fEhqhvKAoU7w+BL9AhChzh9v7sWn9ppDtRFE45tFfsZh0J/8ox5jpnfQ==", + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", + "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", "dev": true, "requires": { - "@sentry/core": "5.27.4", - "@sentry/hub": "5.27.4", - "@sentry/tracing": "5.27.4", - "@sentry/types": "5.27.4", - "@sentry/utils": "5.27.4", + "@sentry/core": "5.30.0", + "@sentry/hub": "5.30.0", + "@sentry/tracing": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", "cookie": "^0.4.1", "https-proxy-agent": "^5.0.0", "lru_map": "^0.3.3", @@ -1122,31 +1062,31 @@ } }, "@sentry/tracing": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.27.4.tgz", - "integrity": "sha512-f3nG8ozCdcbFOzsnBCZ8w+/WfoNiAd0Ctr643L0rsFbaSzPWxbPMe3LNVrWwFVo6mHacG3/2HYmJ3CYMiWyTKQ==", + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", + "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", "dev": true, "requires": { - "@sentry/hub": "5.27.4", - "@sentry/minimal": "5.27.4", - "@sentry/types": "5.27.4", - "@sentry/utils": "5.27.4", + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", "tslib": "^1.9.3" } }, "@sentry/types": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.27.4.tgz", - "integrity": "sha512-41h3c7tgtSS8UBmfvEckSr+7V7/IVOjt/EiydyOd6s0N18zSFfGY5HdA6g+eFtIJK3DhWkUHCHZNanD5IY5YCQ==", + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", + "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", "dev": true }, "@sentry/utils": { - "version": "5.27.4", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.27.4.tgz", - "integrity": "sha512-shV1I/q+Tob3hUxRj11DfMhe9PNDiv85hUUoRloZGGwu275dMwpswb2uwgSmjc2Ao4pnMKVx8TL1hC3kGLVHTQ==", + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", + "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", "dev": true, "requires": { - "@sentry/types": "5.27.4", + "@sentry/types": "5.30.0", "tslib": "^1.9.3" } }, @@ -1241,11 +1181,26 @@ }, "dependencies": { "@types/node": { - "version": "12.19.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", - "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", + "version": "12.20.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.6.tgz", + "integrity": "sha512-sRVq8d+ApGslmkE9e3i+D3gFGk7aZHAT+G4cIpIEdLJYPsWiSPwcAnJEjddLQQDqV3Ra2jOclX/Sv6YrvGYiWA==", "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" + } + }, "eth-lib": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", @@ -1368,9 +1323,9 @@ "dev": true }, "@types/node": { - "version": "10.17.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", - "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "version": "10.17.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.55.tgz", + "integrity": "sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==", "dev": true }, "bn.js": { @@ -1790,7 +1745,7 @@ "requires": { "underscore": "1.9.1", "web3-core-helpers": "1.2.1", - "websocket": "websocket@github:web3-js/WebSocket-Node#polyfill/globalThis" + "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" } }, "web3-shh": { @@ -1899,9 +1854,9 @@ } }, "@types/lodash": { - "version": "4.14.165", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.165.tgz", - "integrity": "sha512-tjSSOTHhI5mCHTy/OOXYIhi2Wt1qcbHmuXD1Ha7q70CgI/I71afO4XtLb/cVexki1oVYchpul/TOuu3Arcdxrg==", + "version": "4.14.168", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz", + "integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==", "dev": true }, "@types/lowdb": { @@ -1947,9 +1902,9 @@ "dev": true }, "@types/node-fetch": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", - "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz", + "integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==", "dev": true, "requires": { "@types/node": "*", @@ -1957,9 +1912,9 @@ }, "dependencies": { "form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", "dev": true, "requires": { "asynckit": "^0.4.0", @@ -1985,15 +1940,15 @@ } }, "@types/prettier": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.5.tgz", - "integrity": "sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.2.3.tgz", + "integrity": "sha512-PijRCG/K3s3w1We6ynUKdxEc5AcuuH3NBmMDP8uvKVp6X43UY7NQlTzczakXP3DJR0F4dfNQIGjU2cUeRYs2AA==", "dev": true }, "@types/qs": { - "version": "6.9.5", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", - "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==", + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA==", "dev": true }, "@types/resolve": { @@ -2015,9 +1970,9 @@ } }, "@types/sinon": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.8.tgz", - "integrity": "sha512-IVnI820FZFMGI+u1R+2VdRaD/82YIQTdqLYC9DLPszZuynAJDtCvCtCs3bmyL66s7FqRM3+LPX7DhHnVTaagDw==", + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.11.tgz", + "integrity": "sha512-PwP4UY33SeeVKodNE37ZlOsR9cReypbMJOhZ7BVE0lB+Hix3efCOxiJWiE5Ia+yL9Cn2Ch72EjFTRze8RZsNtg==", "dev": true, "requires": { "@types/sinonjs__fake-timers": "*" @@ -2040,9 +1995,9 @@ "dev": true }, "@types/underscore": { - "version": "1.10.24", - "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.10.24.tgz", - "integrity": "sha512-T3NQD8hXNW2sRsSbLNjF/aBo18MyJlbw0lSpQHB/eZZtScPdexN4HSa8cByYwTw9Wy7KuOFr81mlDQcQQaZ79w==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.0.tgz", + "integrity": "sha512-ipNAQLgRnG0EWN1cTtfdVHp5AyTW/PAMJ1PxLN4bAKSHbusSZbj48mIHiydQpN7GgQrYqwfnvZ573OVfJm5Nzg==", "dev": true }, "@types/web3": { @@ -2219,12 +2174,6 @@ "color-convert": "^1.9.0" } }, - "antlr4": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.8.0.tgz", - "integrity": "sha512-en/MxQ4OkPgGJQ3wD/muzj1uDnFSzdFIhc2+c6bHZokWkuBb6RRvFjpWhPxWLbgQvaEzldJZ0GSQpfSAaE3hqg==", - "dev": true - }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -2273,24 +2222,6 @@ "sprintf-js": "~1.0.2" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, "array-back": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", @@ -2318,12 +2249,6 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, "arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", @@ -2369,12 +2294,6 @@ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, "async": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", @@ -2411,12 +2330,6 @@ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -2443,61 +2356,6 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, "base-x": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", @@ -2543,9 +2401,9 @@ "dev": true }, "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, "bindings": { @@ -2637,9 +2495,9 @@ "dev": true }, "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, "body-parser": { @@ -2792,9 +2650,9 @@ }, "dependencies": { "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", "dev": true } } @@ -2817,9 +2675,9 @@ }, "dependencies": { "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", "dev": true } } @@ -2918,23 +2776,6 @@ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", "dev": true }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, "cacheable-request": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", @@ -2959,13 +2800,13 @@ } }, "call-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", - "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "requires": { "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.0" + "get-intrinsic": "^1.0.2" } }, "callsites": { @@ -2999,13 +2840,21 @@ } }, "cbor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-5.1.0.tgz", - "integrity": "sha512-qzEc7kUShdMbWTaUH7X+aHW8owvBU3FS0dfYR1lGYpoZr0mGJhhojLlZJH653x/DfeMZ56h315FRNBUIG1R7qg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-5.2.0.tgz", + "integrity": "sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A==", "dev": true, "requires": { - "bignumber.js": "^9.0.0", + "bignumber.js": "^9.0.1", "nofilter": "^1.0.4" + }, + "dependencies": { + "bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", + "dev": true + } } }, "chai": { @@ -3067,14 +2916,14 @@ } }, "chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", "dev": true, "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", - "fsevents": "~2.1.2", + "fsevents": "~2.3.1", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -3104,29 +2953,6 @@ "safe-buffer": "^5.0.1" } }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, "cli-table3": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", @@ -3192,16 +3018,6 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -3261,12 +3077,6 @@ "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", "dev": true }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3373,16 +3183,10 @@ "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", "dev": true }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, "core-js-pure": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.7.0.tgz", - "integrity": "sha512-EZD2ckZysv8MMt4J6HSvS9K2GdtlZtdBncKAmF9lr2n0c9dJUaUN88PSTjvgwCgQPWKTkERXITgS6JJRAnljtg==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.9.1.tgz", + "integrity": "sha512-laz3Zx0avrw9a4QEIdmIblnVuJz8W51leY9iLThatCsFawWxC3sE4guASC78JbCin+DkwMpCdp1AVAuzL/GN7A==", "dev": true }, "core-util-is": { @@ -3415,9 +3219,9 @@ }, "dependencies": { "parse-json": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", - "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -3543,9 +3347,9 @@ "dev": true }, "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -3744,47 +3548,6 @@ } } }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3946,18 +3709,18 @@ "dev": true }, "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "dev": true, "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "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" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" } }, "emoji-regex": { @@ -4039,15 +3802,15 @@ } }, "env-paths": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", - "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true }, "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", "dev": true, "requires": { "prr": "~1.0.1" @@ -4063,22 +3826,27 @@ } }, "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" }, "dependencies": { "object-keys": { @@ -4191,15 +3959,6 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "esprima-extract-comments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz", - "integrity": "sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw==", - "dev": true, - "requires": { - "esprima": "^4.0.0" - } - }, "estraverse": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", @@ -4237,13 +3996,13 @@ } }, "eth-gas-reporter": { - "version": "0.2.19", - "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.19.tgz", - "integrity": "sha512-yQmbAa6O9/Yl/syNml2A0R+ZLQnJ9m9jogFXHzjMWVBMUVnAcEskOVyxaMYddkclZdYIMxE99tQy830C2jLsAQ==", + "version": "0.2.22", + "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.22.tgz", + "integrity": "sha512-L1FlC792aTf3j/j+gGzSNlGrXKSxNPXQNk6TnV5NNZ2w3jnQCRyJjDl0zUo25Cq2t90IS5vGdbkwqFQK7Ce+kw==", "dev": true, "requires": { "@ethersproject/abi": "^5.0.0-beta.146", - "@solidity-parser/parser": "^0.8.0", + "@solidity-parser/parser": "^0.12.0", "cli-table3": "^0.5.0", "colors": "^1.1.2", "ethereumjs-util": "6.2.0", @@ -4260,9 +4019,9 @@ }, "dependencies": { "@solidity-parser/parser": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.8.2.tgz", - "integrity": "sha512-8LySx3qrNXPgB5JiULfG10O3V7QTxI/TLzSw5hFQhXWSkVxZBAv4rZQ0sYgLEbc8g3L2lmnujj1hKul38Eu5NQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.12.0.tgz", + "integrity": "sha512-DT3f/Aa4tQysZwUsuqBwvr8YRJzKkvPUKV/9o2/o5EVw3xqlbzmtx4O60lTUcZdCawL+N8bBLNUyOGpHjGlJVQ==", "dev": true }, "ethereumjs-util": { @@ -4295,6 +4054,23 @@ "setimmediate": "1.0.4", "uuid": "2.0.1", "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "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" + } + } } }, "hash.js": { @@ -4452,9 +4228,9 @@ } }, "ethereum-bloom-filters": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.7.tgz", - "integrity": "sha512-cDcJJSJ9GMAcURiAWO3DxIEhTL/uWqlQnvgKpuYQzYPrt/izuGU+1ntQmHt0IRq6ADoSYHFnB+aCEFIldjhkMQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.9.tgz", + "integrity": "sha512-GiK/RQkAkcVaEdxKVkPcG07PQ5vD7v2MFSHgZmBJSfMzNRHimntdBithsHAT89tAXnIpzVDWt8iaCD1DvkaxGg==", "dev": true, "requires": { "js-sha3": "^0.8.0" @@ -4735,49 +4511,49 @@ }, "dependencies": { "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", "dev": true } } }, "ethers": { - "version": "5.0.19", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.0.19.tgz", - "integrity": "sha512-0AZnUgZh98q888WAd1oI3aLeI+iyDtrupjANVtPPS7O63lVopkR/No8A1NqSkgl/rU+b2iuu2mUZor6GD4RG2w==", + "version": "5.0.32", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.0.32.tgz", + "integrity": "sha512-rORfGWR0HsA4pjKMMcWZorw12DHsXqfIAuPVHJsXt+vI24jvXcVqx+rLsSvgOoLdaCMdxiN5qlIq2+4axKG31g==", "dev": true, "requires": { - "@ethersproject/abi": "5.0.7", - "@ethersproject/abstract-provider": "5.0.5", - "@ethersproject/abstract-signer": "5.0.7", - "@ethersproject/address": "5.0.5", - "@ethersproject/base64": "5.0.4", - "@ethersproject/basex": "5.0.4", - "@ethersproject/bignumber": "5.0.8", - "@ethersproject/bytes": "5.0.5", - "@ethersproject/constants": "5.0.5", - "@ethersproject/contracts": "5.0.5", - "@ethersproject/hash": "5.0.6", - "@ethersproject/hdnode": "5.0.5", - "@ethersproject/json-wallets": "5.0.7", - "@ethersproject/keccak256": "5.0.4", - "@ethersproject/logger": "5.0.6", - "@ethersproject/networks": "5.0.4", - "@ethersproject/pbkdf2": "5.0.4", - "@ethersproject/properties": "5.0.4", - "@ethersproject/providers": "5.0.14", - "@ethersproject/random": "5.0.4", - "@ethersproject/rlp": "5.0.4", - "@ethersproject/sha2": "5.0.4", - "@ethersproject/signing-key": "5.0.5", - "@ethersproject/solidity": "5.0.5", - "@ethersproject/strings": "5.0.5", - "@ethersproject/transactions": "5.0.6", - "@ethersproject/units": "5.0.6", - "@ethersproject/wallet": "5.0.7", - "@ethersproject/web": "5.0.9", - "@ethersproject/wordlists": "5.0.5" + "@ethersproject/abi": "5.0.13", + "@ethersproject/abstract-provider": "5.0.10", + "@ethersproject/abstract-signer": "5.0.14", + "@ethersproject/address": "5.0.11", + "@ethersproject/base64": "5.0.9", + "@ethersproject/basex": "5.0.9", + "@ethersproject/bignumber": "5.0.15", + "@ethersproject/bytes": "5.0.11", + "@ethersproject/constants": "5.0.10", + "@ethersproject/contracts": "5.0.12", + "@ethersproject/hash": "5.0.12", + "@ethersproject/hdnode": "5.0.10", + "@ethersproject/json-wallets": "5.0.12", + "@ethersproject/keccak256": "5.0.9", + "@ethersproject/logger": "5.0.10", + "@ethersproject/networks": "5.0.9", + "@ethersproject/pbkdf2": "5.0.9", + "@ethersproject/properties": "5.0.9", + "@ethersproject/providers": "5.0.24", + "@ethersproject/random": "5.0.9", + "@ethersproject/rlp": "5.0.9", + "@ethersproject/sha2": "5.0.9", + "@ethersproject/signing-key": "5.0.11", + "@ethersproject/solidity": "5.0.10", + "@ethersproject/strings": "5.0.10", + "@ethersproject/transactions": "5.0.11", + "@ethersproject/units": "5.0.11", + "@ethersproject/wallet": "5.0.12", + "@ethersproject/web": "5.0.14", + "@ethersproject/wordlists": "5.0.10" } }, "ethjs-unit": { @@ -4911,56 +4687,6 @@ } } }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -5044,9 +4770,9 @@ }, "dependencies": { "type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", + "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", "dev": true } } @@ -5076,102 +4802,6 @@ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "extract-comments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/extract-comments/-/extract-comments-1.1.0.tgz", - "integrity": "sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q==", - "dev": true, - "requires": { - "esprima-extract-comments": "^1.1.0", - "parse-code-context": "^1.0.0" - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -5200,9 +4830,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", - "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -5211,18 +4841,6 @@ "merge2": "^1.3.0", "micromatch": "^4.0.2", "picomatch": "^2.2.1" - }, - "dependencies": { - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - } } }, "fast-json-stable-stringify": { @@ -5238,9 +4856,9 @@ "dev": true }, "fastq": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz", - "integrity": "sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -5356,35 +4974,21 @@ } }, "find-versions": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", - "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", + "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", "dev": true, "requires": { - "semver-regex": "^2.0.0" + "semver-regex": "^3.1.2" } }, "find-yarn-workspace-root": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz", - "integrity": "sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", "dev": true, "requires": { - "fs-extra": "^4.0.3", - "micromatch": "^3.1.4" - }, - "dependencies": { - "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - } + "micromatch": "^4.0.2" } }, "flat": { @@ -5403,16 +5007,19 @@ "dev": true }, "follow-redirects": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", - "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", + "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==", "dev": true }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } }, "forever-agent": { "version": "0.6.1", @@ -5443,15 +5050,6 @@ "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", "dev": true }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -5544,9 +5142,9 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, @@ -5575,14 +5173,12 @@ "dependencies": { "ansi-regex": { "version": "4.1.0", - "resolved": false, - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "bundled": true, "dev": true }, "ansi-styles": { "version": "3.2.1", - "resolved": false, - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "bundled": true, "dev": true, "requires": { "color-convert": "^1.9.0" @@ -5590,8 +5186,7 @@ }, "bindings": { "version": "1.5.0", - "resolved": false, - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "bundled": true, "dev": true, "requires": { "file-uri-to-path": "1.0.0" @@ -5599,8 +5194,7 @@ }, "bip66": { "version": "1.1.5", - "resolved": false, - "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "bundled": true, "dev": true, "requires": { "safe-buffer": "^5.0.1" @@ -5608,20 +5202,17 @@ }, "bn.js": { "version": "4.11.8", - "resolved": false, - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "bundled": true, "dev": true }, "brorand": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "bundled": true, "dev": true }, "browserify-aes": { "version": "1.2.0", - "resolved": false, - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "bundled": true, "dev": true, "requires": { "buffer-xor": "^1.0.3", @@ -5634,26 +5225,22 @@ }, "buffer-from": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "bundled": true, "dev": true }, "buffer-xor": { "version": "1.0.3", - "resolved": false, - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "bundled": true, "dev": true }, "camelcase": { "version": "5.3.1", - "resolved": false, - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "bundled": true, "dev": true }, "cipher-base": { "version": "1.0.4", - "resolved": false, - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "bundled": true, "dev": true, "requires": { "inherits": "^2.0.1", @@ -5662,8 +5249,7 @@ }, "cliui": { "version": "5.0.0", - "resolved": false, - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "bundled": true, "dev": true, "requires": { "string-width": "^3.1.0", @@ -5673,8 +5259,7 @@ }, "color-convert": { "version": "1.9.3", - "resolved": false, - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "bundled": true, "dev": true, "requires": { "color-name": "1.1.3" @@ -5682,14 +5267,12 @@ }, "color-name": { "version": "1.1.3", - "resolved": false, - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "bundled": true, "dev": true }, "create-hash": { "version": "1.2.0", - "resolved": false, - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "bundled": true, "dev": true, "requires": { "cipher-base": "^1.0.1", @@ -5701,8 +5284,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": false, - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "bundled": true, "dev": true, "requires": { "cipher-base": "^1.0.3", @@ -5715,8 +5297,7 @@ }, "cross-spawn": { "version": "6.0.5", - "resolved": false, - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "bundled": true, "dev": true, "requires": { "nice-try": "^1.0.4", @@ -5728,14 +5309,12 @@ }, "decamelize": { "version": "1.2.0", - "resolved": false, - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "bundled": true, "dev": true }, "drbg.js": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "bundled": true, "dev": true, "requires": { "browserify-aes": "^1.0.6", @@ -5745,8 +5324,7 @@ }, "elliptic": { "version": "6.5.0", - "resolved": false, - "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "bundled": true, "dev": true, "requires": { "bn.js": "^4.4.0", @@ -5760,14 +5338,12 @@ }, "emoji-regex": { "version": "7.0.3", - "resolved": false, - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "bundled": true, "dev": true }, "end-of-stream": { "version": "1.4.1", - "resolved": false, - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "bundled": true, "dev": true, "requires": { "once": "^1.4.0" @@ -5775,8 +5351,7 @@ }, "ethereumjs-util": { "version": "6.1.0", - "resolved": false, - "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "bundled": true, "dev": true, "requires": { "bn.js": "^4.11.0", @@ -5790,8 +5365,7 @@ }, "ethjs-util": { "version": "0.1.6", - "resolved": false, - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "bundled": true, "dev": true, "requires": { "is-hex-prefixed": "1.0.0", @@ -5800,8 +5374,7 @@ }, "evp_bytestokey": { "version": "1.0.3", - "resolved": false, - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "bundled": true, "dev": true, "requires": { "md5.js": "^1.3.4", @@ -5810,8 +5383,7 @@ }, "execa": { "version": "1.0.0", - "resolved": false, - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "bundled": true, "dev": true, "requires": { "cross-spawn": "^6.0.0", @@ -5825,14 +5397,12 @@ }, "file-uri-to-path": { "version": "1.0.0", - "resolved": false, - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "bundled": true, "dev": true }, "find-up": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "bundled": true, "dev": true, "requires": { "locate-path": "^3.0.0" @@ -5840,14 +5410,12 @@ }, "get-caller-file": { "version": "2.0.5", - "resolved": false, - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "bundled": true, "dev": true }, "get-stream": { "version": "4.1.0", - "resolved": false, - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "bundled": true, "dev": true, "requires": { "pump": "^3.0.0" @@ -5855,8 +5423,7 @@ }, "hash-base": { "version": "3.0.4", - "resolved": false, - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "bundled": true, "dev": true, "requires": { "inherits": "^2.0.1", @@ -5865,8 +5432,7 @@ }, "hash.js": { "version": "1.1.7", - "resolved": false, - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "bundled": true, "dev": true, "requires": { "inherits": "^2.0.3", @@ -5875,8 +5441,7 @@ }, "hmac-drbg": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "bundled": true, "dev": true, "requires": { "hash.js": "^1.0.3", @@ -5886,44 +5451,37 @@ }, "inherits": { "version": "2.0.4", - "resolved": false, - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "bundled": true, "dev": true }, "invert-kv": { "version": "2.0.0", - "resolved": false, - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "bundled": true, "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "bundled": true, "dev": true }, "is-hex-prefixed": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", + "bundled": true, "dev": true }, "is-stream": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "bundled": true, "dev": true }, "isexe": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "bundled": true, "dev": true }, "keccak": { "version": "1.4.0", - "resolved": false, - "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "bundled": true, "dev": true, "requires": { "bindings": "^1.2.1", @@ -5934,8 +5492,7 @@ }, "lcid": { "version": "2.0.0", - "resolved": false, - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "bundled": true, "dev": true, "requires": { "invert-kv": "^2.0.0" @@ -5943,8 +5500,7 @@ }, "locate-path": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "bundled": true, "dev": true, "requires": { "p-locate": "^3.0.0", @@ -5953,8 +5509,7 @@ }, "map-age-cleaner": { "version": "0.1.3", - "resolved": false, - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "bundled": true, "dev": true, "requires": { "p-defer": "^1.0.0" @@ -5962,8 +5517,7 @@ }, "md5.js": { "version": "1.3.5", - "resolved": false, - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "bundled": true, "dev": true, "requires": { "hash-base": "^3.0.0", @@ -5973,8 +5527,7 @@ }, "mem": { "version": "4.3.0", - "resolved": false, - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "bundled": true, "dev": true, "requires": { "map-age-cleaner": "^0.1.1", @@ -5984,38 +5537,32 @@ }, "mimic-fn": { "version": "2.1.0", - "resolved": false, - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "bundled": true, "dev": true }, "minimalistic-assert": { "version": "1.0.1", - "resolved": false, - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "bundled": true, "dev": true }, "minimalistic-crypto-utils": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "bundled": true, "dev": true }, "nan": { "version": "2.14.0", - "resolved": false, - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "bundled": true, "dev": true }, "nice-try": { "version": "1.0.5", - "resolved": false, - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "bundled": true, "dev": true }, "npm-run-path": { "version": "2.0.2", - "resolved": false, - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "bundled": true, "dev": true, "requires": { "path-key": "^2.0.0" @@ -6023,8 +5570,7 @@ }, "once": { "version": "1.4.0", - "resolved": false, - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, "dev": true, "requires": { "wrappy": "1" @@ -6032,8 +5578,7 @@ }, "os-locale": { "version": "3.1.0", - "resolved": false, - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "bundled": true, "dev": true, "requires": { "execa": "^1.0.0", @@ -6043,26 +5588,22 @@ }, "p-defer": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "bundled": true, "dev": true }, "p-finally": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "bundled": true, "dev": true }, "p-is-promise": { "version": "2.1.0", - "resolved": false, - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "bundled": true, "dev": true }, "p-limit": { "version": "2.2.0", - "resolved": false, - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "bundled": true, "dev": true, "requires": { "p-try": "^2.0.0" @@ -6070,8 +5611,7 @@ }, "p-locate": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "bundled": true, "dev": true, "requires": { "p-limit": "^2.0.0" @@ -6079,26 +5619,22 @@ }, "p-try": { "version": "2.2.0", - "resolved": false, - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "bundled": true, "dev": true }, "path-exists": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "bundled": true, "dev": true }, "path-key": { "version": "2.0.1", - "resolved": false, - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "bundled": true, "dev": true }, "pump": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "bundled": true, "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -6107,20 +5643,17 @@ }, "require-directory": { "version": "2.1.1", - "resolved": false, - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "bundled": true, "dev": true }, "require-main-filename": { "version": "2.0.0", - "resolved": false, - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "bundled": true, "dev": true }, "ripemd160": { "version": "2.0.2", - "resolved": false, - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "bundled": true, "dev": true, "requires": { "hash-base": "^3.0.0", @@ -6129,8 +5662,7 @@ }, "rlp": { "version": "2.2.3", - "resolved": false, - "integrity": "sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==", + "bundled": true, "dev": true, "requires": { "bn.js": "^4.11.1", @@ -6139,14 +5671,12 @@ }, "safe-buffer": { "version": "5.2.0", - "resolved": false, - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "bundled": true, "dev": true }, "secp256k1": { "version": "3.7.1", - "resolved": false, - "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", + "bundled": true, "dev": true, "requires": { "bindings": "^1.5.0", @@ -6161,20 +5691,17 @@ }, "semver": { "version": "5.7.0", - "resolved": false, - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "bundled": true, "dev": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, "dev": true }, "sha.js": { "version": "2.4.11", - "resolved": false, - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "bundled": true, "dev": true, "requires": { "inherits": "^2.0.1", @@ -6183,8 +5710,7 @@ }, "shebang-command": { "version": "1.2.0", - "resolved": false, - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "bundled": true, "dev": true, "requires": { "shebang-regex": "^1.0.0" @@ -6192,26 +5718,22 @@ }, "shebang-regex": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "bundled": true, "dev": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, "dev": true }, "source-map": { "version": "0.6.1", - "resolved": false, - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "bundled": true, "dev": true }, "source-map-support": { "version": "0.5.12", - "resolved": false, - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "bundled": true, "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -6220,8 +5742,7 @@ }, "string-width": { "version": "3.1.0", - "resolved": false, - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "bundled": true, "dev": true, "requires": { "emoji-regex": "^7.0.1", @@ -6231,8 +5752,7 @@ }, "strip-ansi": { "version": "5.2.0", - "resolved": false, - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "bundled": true, "dev": true, "requires": { "ansi-regex": "^4.1.0" @@ -6240,14 +5760,12 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "bundled": true, "dev": true }, "strip-hex-prefix": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "bundled": true, "dev": true, "requires": { "is-hex-prefixed": "1.0.0" @@ -6255,8 +5773,7 @@ }, "which": { "version": "1.3.1", - "resolved": false, - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "bundled": true, "dev": true, "requires": { "isexe": "^2.0.0" @@ -6264,14 +5781,12 @@ }, "which-module": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "bundled": true, "dev": true }, "wrap-ansi": { "version": "5.1.0", - "resolved": false, - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "bundled": true, "dev": true, "requires": { "ansi-styles": "^3.2.0", @@ -6281,20 +5796,17 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "bundled": true, "dev": true }, "y18n": { "version": "4.0.0", - "resolved": false, - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "bundled": true, "dev": true }, "yargs": { "version": "13.2.4", - "resolved": false, - "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", + "bundled": true, "dev": true, "requires": { "cliui": "^5.0.0", @@ -6312,8 +5824,7 @@ }, "yargs-parser": { "version": "13.1.1", - "resolved": false, - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "bundled": true, "dev": true, "requires": { "camelcase": "^5.0.0", @@ -6323,9 +5834,9 @@ } }, "ganache-core": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/ganache-core/-/ganache-core-2.13.1.tgz", - "integrity": "sha512-Ewg+kNcDqXtOohe7jCcP+ZUv9EMzOx2MoqOYYP3BCfxrDh3KjBXXaKK+Let7li0TghAs9lxmBgevZku35j5YzA==", + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/ganache-core/-/ganache-core-2.13.2.tgz", + "integrity": "sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw==", "dev": true, "requires": { "abstract-leveldown": "3.0.0", @@ -6335,7 +5846,7 @@ "clone": "2.1.2", "debug": "3.2.6", "encoding-down": "5.0.4", - "eth-sig-util": "^2.0.0", + "eth-sig-util": "3.0.0", "ethereumjs-abi": "0.6.8", "ethereumjs-account": "3.0.0", "ethereumjs-block": "2.2.2", @@ -6378,146 +5889,213 @@ "@ethersproject/strings": ">=5.0.0-beta.130" } }, - "@ethersproject/address": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.5.tgz", - "integrity": "sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA==", + "@ethersproject/abstract-provider": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.8.tgz", + "integrity": "sha512-fqJXkewcGdi8LogKMgRyzc/Ls2js07yor7+g9KfPs09uPOcQLg7cc34JN+lk34HH9gg2HU0DIA5797ZR8znkfw==", "dev": true, "optional": true, "requires": { - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/rlp": "^5.0.3", - "bn.js": "^4.4.0" + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/networks": "^5.0.7", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/transactions": "^5.0.9", + "@ethersproject/web": "^5.0.12" + } + }, + "@ethersproject/abstract-signer": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.10.tgz", + "integrity": "sha512-irx7kH7FDAeW7QChDPW19WsxqeB1d3XLyOLSXm0bfPqL1SS07LXWltBJUBUxqC03ORpAOcM3JQj57DU8JnVY2g==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/abstract-provider": "^5.0.8", + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7" + } + }, + "@ethersproject/address": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.9.tgz", + "integrity": "sha512-gKkmbZDMyGbVjr8nA5P0md1GgESqSGH7ILIrDidPdNXBl4adqbuA3OAuZx/O2oGpL6PtJ9BDa0kHheZ1ToHU3w==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/keccak256": "^5.0.7", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/rlp": "^5.0.7" + } + }, + "@ethersproject/base64": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.7.tgz", + "integrity": "sha512-S5oh5DVfCo06xwJXT8fQC68mvJfgScTl2AXvbYMsHNfIBTDb084Wx4iA9MNlEReOv6HulkS+gyrUM/j3514rSw==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.9" } }, "@ethersproject/bignumber": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.8.tgz", - "integrity": "sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA==", + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.13.tgz", + "integrity": "sha512-b89bX5li6aK492yuPP5mPgRVgIxxBP7ksaBtKX5QQBsrZTpNOjf/MR4CjcUrAw8g+RQuD6kap9lPjFgY4U1/5A==", "dev": true, "optional": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", "bn.js": "^4.4.0" } }, "@ethersproject/bytes": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.5.tgz", - "integrity": "sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.9.tgz", + "integrity": "sha512-k+17ZViDtAugC0s7HM6rdsTWEdIYII4RPCDkPEuxKc6i40Bs+m6tjRAtCECX06wKZnrEoR9pjOJRXHJ/VLoOcA==", "dev": true, "optional": true, "requires": { - "@ethersproject/logger": "^5.0.5" + "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/constants": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.5.tgz", - "integrity": "sha512-foaQVmxp2+ik9FrLUCtVrLZCj4M3Ibgkqvh+Xw/vFRSerkjVSYePApaVE5essxhoSlF1U9oXfWY09QI2AXtgKA==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.8.tgz", + "integrity": "sha512-sCc73pFBsl59eDfoQR5OCEZCRv5b0iywadunti6MQIr5lt3XpwxK1Iuzd8XSFO02N9jUifvuZRrt0cY0+NBgTg==", "dev": true, "optional": true, "requires": { - "@ethersproject/bignumber": "^5.0.7" + "@ethersproject/bignumber": "^5.0.13" } }, "@ethersproject/hash": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.5.tgz", - "integrity": "sha512-GpI80/h2HDpfNKpCZoxQJCjOQloGnlD5hM1G+tZe8FQDJhEvFjJoPDuWv+NaYjJfOciKS2Axqc4Q4WamdLoUgg==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.10.tgz", + "integrity": "sha512-Tf0bvs6YFhw28LuHnhlDWyr0xfcDxSXdwM4TcskeBbmXVSKLv3bJQEEEBFUcRX0fJuslR3gCVySEaSh7vuMx5w==", "dev": true, "optional": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/strings": "^5.0.4" + "@ethersproject/abstract-signer": "^5.0.10", + "@ethersproject/address": "^5.0.9", + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/keccak256": "^5.0.7", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/strings": "^5.0.8" } }, "@ethersproject/keccak256": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.4.tgz", - "integrity": "sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.7.tgz", + "integrity": "sha512-zpUBmofWvx9PGfc7IICobgFQSgNmTOGTGLUxSYqZzY/T+b4y/2o5eqf/GGmD7qnTGzKQ42YlLNo+LeDP2qe55g==", "dev": true, "optional": true, "requires": { - "@ethersproject/bytes": "^5.0.4", + "@ethersproject/bytes": "^5.0.9", "js-sha3": "0.5.7" } }, "@ethersproject/logger": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.6.tgz", - "integrity": "sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.8.tgz", + "integrity": "sha512-SkJCTaVTnaZ3/ieLF5pVftxGEFX56pTH+f2Slrpv7cU0TNpUZNib84QQdukd++sWUp/S7j5t5NW+WegbXd4U/A==", "dev": true, "optional": true }, - "@ethersproject/properties": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.4.tgz", - "integrity": "sha512-UdyX3GqBxFt15B0uSESdDNmhvEbK3ACdDXl2soshoPcneXuTswHDeA0LoPlnaZzhbgk4p6jqb4GMms5C26Qu6A==", + "@ethersproject/networks": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.7.tgz", + "integrity": "sha512-dI14QATndIcUgcCBL1c5vUr/YsI5cCHLN81rF7PU+yS7Xgp2/Rzbr9+YqpC6NBXHFUASjh6GpKqsVMpufAL0BQ==", "dev": true, "optional": true, "requires": { - "@ethersproject/logger": "^5.0.5" + "@ethersproject/logger": "^5.0.8" + } + }, + "@ethersproject/properties": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.7.tgz", + "integrity": "sha512-812H1Rus2vjw0zbasfDI1GLNPDsoyX1pYqiCgaR1BuyKxUTbwcH1B+214l6VGe1v+F6iEVb7WjIwMjKhb4EUsg==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/rlp": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.4.tgz", - "integrity": "sha512-5qrrZad7VTjofxSsm7Zg/7Dr4ZOln4S2CqiDdOuTv6MBKnXj0CiBojXyuDy52M8O3wxH0CyE924hXWTDV1PQWQ==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.7.tgz", + "integrity": "sha512-ulUTVEuV7PT4jJTPpfhRHK57tkLEDEY9XSYJtrSNHOqdwMvH0z7BM2AKIMq4LVDlnu4YZASdKrkFGEIO712V9w==", "dev": true, "optional": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5" + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/signing-key": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.5.tgz", - "integrity": "sha512-Z1wY7JC1HVO4CvQWY2TyTTuAr8xK3bJijZw1a9G92JEmKdv1j255R/0YLBBcFTl2J65LUjtXynNJ2GbArPGi5g==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.8.tgz", + "integrity": "sha512-YKxQM45eDa6WAD+s3QZPdm1uW1MutzVuyoepdRRVmMJ8qkk7iOiIhUkZwqKLNxKzEJijt/82ycuOREc9WBNAKg==", "dev": true, "optional": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7", "elliptic": "6.5.3" } }, "@ethersproject/strings": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.5.tgz", - "integrity": "sha512-JED6WaIV00xM/gvj8vSnd+0VWtDYdidTmavFRCTQakqfz+4tDo6Jz5LHgG+dd45h7ah7ykCHW0C7ZXWEDROCXQ==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.8.tgz", + "integrity": "sha512-5IsdXf8tMY8QuHl8vTLnk9ehXDDm6x9FB9S9Og5IA1GYhLe5ZewydXSjlJlsqU2t9HRbfv97OJZV/pX8DVA/Hw==", "dev": true, "optional": true, "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/logger": "^5.0.5" + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/constants": "^5.0.8", + "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/transactions": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.6.tgz", - "integrity": "sha512-htsFhOD+NMBxx676A8ehSuwVV49iqpSB+CkjPZ02tpNew0K6p8g0CZ46Z1ZP946gIHAU80xQ0NACHYrjIUaCFA==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.9.tgz", + "integrity": "sha512-0Fu1yhdFBkrbMjenEr+39tmDxuHmaw0pe9Jb18XuKoItj7Z3p7+UzdHLr2S/okvHDHYPbZE5gtANDdQ3ZL1nBA==", "dev": true, "optional": true, "requires": { - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/rlp": "^5.0.3", - "@ethersproject/signing-key": "^5.0.4" + "@ethersproject/address": "^5.0.9", + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/constants": "^5.0.8", + "@ethersproject/keccak256": "^5.0.7", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/rlp": "^5.0.7", + "@ethersproject/signing-key": "^5.0.8" + } + }, + "@ethersproject/web": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.12.tgz", + "integrity": "sha512-gVxS5iW0bgidZ76kr7LsTxj4uzN5XpCLzvZrLp8TP+4YgxHfCeetFyQkRPgBEAJdNrexdSBayvyJvzGvOq0O8g==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/base64": "^5.0.7", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/strings": "^5.0.8" } }, "@sindresorhus/is": { @@ -6547,9 +6125,9 @@ } }, "@types/node": { - "version": "14.11.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.8.tgz", - "integrity": "sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw==", + "version": "14.14.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz", + "integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A==", "dev": true }, "@types/pbkdf2": { @@ -6604,9 +6182,9 @@ "optional": true }, "ajv": { - "version": "6.12.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", - "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -6732,9 +6310,9 @@ "dev": true }, "aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "dev": true }, "babel-code-frame": { @@ -7546,9 +7124,9 @@ } }, "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true }, "bcrypt-pbkdf": { @@ -7708,14 +7286,23 @@ } }, "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", "dev": true, "optional": true, "requires": { - "bn.js": "^4.1.0", + "bn.js": "^5.0.0", "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true, + "optional": true + } } }, "browserify-sign": { @@ -7788,13 +7375,13 @@ } }, "buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "buffer-from": { @@ -7817,20 +7404,12 @@ "dev": true }, "bufferutil": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", - "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz", + "integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==", "dev": true, "requires": { - "node-gyp-build": "~3.7.0" - }, - "dependencies": { - "node-gyp-build": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", - "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", - "dev": true - } + "node-gyp-build": "^4.2.0" } }, "bytes": { @@ -7931,10 +7510,20 @@ } } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "caniuse-lite": { - "version": "1.0.30001146", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001146.tgz", - "integrity": "sha512-VAy5RHDfTJhpxnDdp2n40GPPLp3KqNrXz1QqFv4J64HvArKs8nuNMOWkB3ICOaBTU/Aj4rYAo/ytdQDDFF/Pug==", + "version": "1.0.30001174", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001174.tgz", + "integrity": "sha512-tqClL/4ThQq6cfFXH3oJL4rifFBeM6gTkphjao5kgwMaW9yn0tKgQLAEfKzDwj6HQWCB/aWo8kTFlSvIN8geEA==", "dev": true }, "caseless": { @@ -8263,15 +7852,15 @@ "dev": true }, "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", "dev": true }, "core-js-pure": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", - "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.8.2.tgz", + "integrity": "sha512-v6zfIQqL/pzTVAbZvYUozsxNfxcFb6Ks3ZfEbuneJl3FW9Jb8F6vLWB6f+qTmAu72msUdyb84V8d/yBFf7FNnw==", "dev": true }, "core-util-is": { @@ -8562,9 +8151,9 @@ "optional": true }, "electron-to-chromium": { - "version": "1.3.578", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.578.tgz", - "integrity": "sha512-z4gU6dA1CbBJsAErW5swTGAaU2TBzc2mPAonJb00zqW1rOraDo2zfBMDRvaz9cVic+0JEZiYbHWPw/fTaZlG2Q==", + "version": "1.3.636", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.636.tgz", + "integrity": "sha512-Adcvng33sd3gTjNIDNXGD1G4H6qCImIy2euUJAQHtLNplEKU5WEz5KRJxupRNIIT8sD5oFZLTKBWAf12Bsz24A==", "dev": true }, "elliptic": { @@ -8643,18 +8232,18 @@ } }, "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", "dev": true, "requires": { "prr": "~1.0.1" } }, "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", @@ -8662,6 +8251,7 @@ "has": "^1.0.3", "has-symbols": "^1.0.1", "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", "is-regex": "^1.1.1", "object-inspect": "^1.8.0", "object-keys": "^1.1.1", @@ -9184,9 +8774,9 @@ } }, "eth-sig-util": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.3.0.tgz", - "integrity": "sha512-ugD1AvaggvKaZDgnS19W5qOfepjGc7qHrt7TrAaL54gJw9SHvgIXJ3r2xOMW30RWJZNP+1GlTOy5oye7yXA4xA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-3.0.0.tgz", + "integrity": "sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ==", "dev": true, "requires": { "buffer": "^5.2.1", @@ -9612,9 +9202,9 @@ } }, "ethereumjs-util": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.6.tgz", - "integrity": "sha512-E9aJ9W7XZkcBqIblfstBU+0nGSjF9Dz/Ps7s1NTFOgDZM8pwD+nX1P1GBJeSqB6Osxhj2UtuxVCqjvmrj2svzw==", + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.7.tgz", + "integrity": "sha512-vU5rtZBlZsgkTw3o6PDKyB8li2EgLavnAbsKcfsH2YhHH1Le+PP8vEiMnAnvgc1B6uMoaM5GDCrVztBw0Q5K9g==", "dev": true, "requires": { "@types/bn.js": "^4.11.3", @@ -10853,6 +10443,17 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "get-intrinsic": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", + "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, "get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -10893,21 +10494,13 @@ } }, "global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", "dev": true, "requires": { "min-document": "^2.19.0", - "process": "~0.5.1" - }, - "dependencies": { - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true - } + "process": "^0.11.10" } }, "got": { @@ -11216,9 +10809,9 @@ } }, "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true }, "immediate": { @@ -11269,10 +10862,13 @@ } }, "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } }, "is-callable": { "version": "1.2.2", @@ -11349,15 +10945,15 @@ "dev": true }, "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", "dev": true }, "is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", "dev": true, "optional": true }, @@ -11893,18 +11489,18 @@ "optional": true }, "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", "dev": true }, "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", "dev": true, "requires": { - "mime-db": "1.44.0" + "mime-db": "1.45.0" } }, "mimic-response": { @@ -12010,9 +11606,9 @@ "optional": true }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "multibase": { @@ -12238,41 +11834,19 @@ } }, "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", "dev": true }, "object-is": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", - "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.4.tgz", + "integrity": "sha512-1ZvAZ4wlF7IyPVOcE1Omikt7UpaFlOQq0HlSti+ZvDH3UiD2brwGMwDbyV43jao2bKJ+4+WdPJHSd7kgzKYVqg==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" } }, "object-keys": { @@ -12291,47 +11865,26 @@ } }, "object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dev": true, "requires": { + "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", "has-symbols": "^1.0.1", "object-keys": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } } }, "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz", + "integrity": "sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng==", "dev": true, "requires": { + "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "es-abstract": "^1.18.0-next.1" } }, "object.pick": { @@ -12592,6 +12145,12 @@ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -12809,9 +12368,9 @@ } }, "regenerate": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", - "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", "dev": true }, "regenerator-runtime": { @@ -12849,6 +12408,27 @@ "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "regexpu-core": { @@ -12934,15 +12514,6 @@ "uuid": "^3.3.2" } }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -13593,55 +13164,34 @@ "optional": true }, "string.prototype.trim": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.2.tgz", - "integrity": "sha512-b5yrbl3BXIjHau9Prk7U0RRYcUYdN4wGSVaqoBQS50CCE3KBuYU0TYRNPFCP7aVoNMX87HKThdMRVIP3giclKg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.3.tgz", + "integrity": "sha512-16IL9pIBA5asNOSukPfxX2W68BaBvxyiRK16H3RA/lWW9BDosh+w7f+LhomPHpXJ82QEe7w7/rY/S1CV97raLg==", "dev": true, "requires": { + "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "es-abstract": "^1.18.0-next.1" } }, "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", + "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", + "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" } }, "string_decoder": { @@ -13825,6 +13375,15 @@ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } } } }, @@ -14135,9 +13694,9 @@ } }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { "punycode": "^2.1.0" @@ -14180,20 +13739,12 @@ "dev": true }, "utf-8-validate": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz", - "integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.4.tgz", + "integrity": "sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==", "dev": true, "requires": { - "node-gyp-build": "~3.7.0" - }, - "dependencies": { - "node-gyp-build": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", - "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", - "dev": true - } + "node-gyp-build": "^4.2.0" } }, "utf8": { @@ -14210,15 +13761,16 @@ "dev": true }, "util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.1.1.tgz", + "integrity": "sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw==", "dev": true, "requires": { + "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", + "for-each": "^0.3.3", "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" + "object.getownpropertydescriptors": "^2.1.1" } }, "utils-merge": { @@ -14289,9 +13841,9 @@ }, "dependencies": { "@types/node": { - "version": "12.12.67", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz", - "integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg==", + "version": "12.19.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.12.tgz", + "integrity": "sha512-UwfL2uIU9arX/+/PRcIkT08/iBadGN2z6ExOROA2Dh5mAuWTBj6iJbQX4nekiV5H8cTrEG569LeX+HRco9Cbxw==", "dev": true, "optional": true } @@ -14314,9 +13866,9 @@ }, "dependencies": { "@types/node": { - "version": "12.12.67", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz", - "integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg==", + "version": "12.19.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.12.tgz", + "integrity": "sha512-UwfL2uIU9arX/+/PRcIkT08/iBadGN2z6ExOROA2Dh5mAuWTBj6iJbQX4nekiV5H8cTrEG569LeX+HRco9Cbxw==", "dev": true, "optional": true } @@ -14523,9 +14075,9 @@ }, "dependencies": { "@types/node": { - "version": "12.12.67", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz", - "integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg==", + "version": "12.19.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.12.tgz", + "integrity": "sha512-UwfL2uIU9arX/+/PRcIkT08/iBadGN2z6ExOROA2Dh5mAuWTBj6iJbQX4nekiV5H8cTrEG569LeX+HRco9Cbxw==", "dev": true, "optional": true } @@ -14595,13 +14147,13 @@ "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", "dev": true, "requires": { - "ethereumjs-abi": "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git", + "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "ethereumjs-util": "^5.1.1" } }, "ethereumjs-abi": { - "version": "git+https://git@github.com/ethereumjs/ethereumjs-abi.git#1ce6a1d64235fabe2aaf827fd606def55693508f", - "from": "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git", + "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#1a27c59c15ab1e95ee8e5c4ed6ad814c49cc439e", + "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "dev": true, "requires": { "bn.js": "^4.11.8", @@ -15088,12 +14640,12 @@ } }, "xhr": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", - "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", "dev": true, "requires": { - "global": "~4.3.0", + "global": "~4.4.0", "is-function": "^1.0.1", "parse-headers": "^2.0.0", "xtend": "^4.0.0" @@ -15168,9 +14720,9 @@ "dev": true }, "get-intrinsic": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", - "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "dev": true, "requires": { "function-bind": "^1.1.1", @@ -15199,12 +14751,6 @@ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -15238,22 +14784,22 @@ } }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" } }, "global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", "dev": true, "requires": { "min-document": "^2.19.0", - "process": "~0.5.1" + "process": "^0.11.10" } }, "global-dirs": { @@ -15286,9 +14832,9 @@ } }, "globby": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", - "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", + "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", "dev": true, "requires": { "array-union": "^2.1.0", @@ -15325,9 +14871,9 @@ } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "dev": true }, "growl": { @@ -15337,9 +14883,9 @@ "dev": true }, "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, "requires": { "minimist": "^1.2.5", @@ -15366,12 +14912,12 @@ } }, "hardhat": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.0.8.tgz", - "integrity": "sha512-2tDAtOfshrBzP103dx7PQrhTwv2sqjhQStZAPwkkQTic25o2EH6HYE2++LuOG98YwqSjr0WvhvdBvKl3dCSkYA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.1.1.tgz", + "integrity": "sha512-55XMqB5QoeRg3m56rBg0NQgU//GPqOC9t4RbRSU3pdBJGHGXFTUh8fjTPxnWJNu9r72Zju++syGcCkPGwftyvw==", "dev": true, "requires": { - "@nomiclabs/ethereumjs-vm": "^4.1.1", + "@nomiclabs/ethereumjs-vm": "4.2.2", "@sentry/node": "^5.18.1", "@solidity-parser/parser": "^0.11.0", "@types/bn.js": "^4.11.5", @@ -15389,10 +14935,10 @@ "ethereum-cryptography": "^0.1.2", "ethereumjs-abi": "^0.6.8", "ethereumjs-account": "^3.0.0", - "ethereumjs-block": "^2.2.0", + "ethereumjs-block": "^2.2.2", "ethereumjs-common": "^1.5.0", - "ethereumjs-tx": "^2.1.1", - "ethereumjs-util": "^6.1.0", + "ethereumjs-tx": "^2.1.2", + "ethereumjs-util": "^6.2.0", "find-up": "^2.1.0", "fp-ts": "1.19.3", "fs-extra": "^7.0.1", @@ -15400,7 +14946,8 @@ "immutable": "^4.0.0-rc.12", "io-ts": "1.10.4", "lodash": "^4.17.11", - "merkle-patricia-tree": "^3.0.0", + "merkle-patricia-tree": "3.0.0", + "mnemonist": "^0.38.0", "mocha": "^7.1.2", "node-fetch": "^2.6.0", "qs": "^6.7.0", @@ -15521,18 +15068,19 @@ } }, "hardhat-gas-reporter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.1.tgz", - "integrity": "sha512-YC+SCYIkBdRtISNbisU2BwDSelUdCrIKRsJXt3M9Jw1VF5CmtSZb8VuuOc2Zl4AMcEV2jEy6ZuAksYomPiApYQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.4.tgz", + "integrity": "sha512-G376zKh81G3K9WtDA+SoTLWsoygikH++tD1E7llx+X7J+GbIqfwhDKKgvJjcnEesMrtR9UqQHK02lJuXY1RTxw==", "dev": true, "requires": { - "eth-gas-reporter": "^0.2.19" + "eth-gas-reporter": "^0.2.20", + "sha1": "^1.1.1" } }, "hardhat-typechain": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/hardhat-typechain/-/hardhat-typechain-0.3.3.tgz", - "integrity": "sha512-NrqP7Zng28prV3YT0lXoo1pXtZxoNCMfiZIWkf1HXjjID42JLLfSOTsvlb0okDMpz4tJaEEkgADJO69sKZxw+Q==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/hardhat-typechain/-/hardhat-typechain-0.3.5.tgz", + "integrity": "sha512-w9lm8sxqTJACY+V7vijiH+NkPExnmtiQEjsV9JKD1KgMdVk2q8y+RhvU/c4B7+7b1+HylRUCxpOIvFuB3rE4+w==", "dev": true }, "has": { @@ -15544,6 +15092,12 @@ "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -15557,9 +15111,9 @@ "dev": true }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, "has-to-string-tag-x": { @@ -15571,64 +15125,6 @@ "has-symbol-support-x": "^1.4.1" } }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", @@ -15720,9 +15216,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", - "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "version": "10.17.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.55.tgz", + "integrity": "sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==", "dev": true } } @@ -15749,18 +15245,18 @@ } }, "husky": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz", - "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==", + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz", + "integrity": "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==", "dev": true, "requires": { "chalk": "^4.0.0", "ci-info": "^2.0.0", "compare-versions": "^3.6.0", "cosmiconfig": "^7.0.0", - "find-versions": "^3.2.0", + "find-versions": "^4.0.0", "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^4.2.0", + "pkg-dir": "^5.0.0", "please-upgrade-node": "^3.2.0", "slash": "^3.0.0", "which-pm-runs": "^1.0.0" @@ -15860,9 +15356,9 @@ "dev": true }, "import-fresh": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", - "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -15892,9 +15388,9 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, "interpret": { @@ -15934,38 +15430,18 @@ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", + "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "dev": true + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -15975,6 +15451,15 @@ "binary-extensions": "^2.0.0" } }, + "is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, "is-buffer": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", @@ -15982,9 +15467,9 @@ "dev": true }, "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", "dev": true }, "is-ci": { @@ -15997,69 +15482,24 @@ } }, "is-core-module": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz", - "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", "dev": true, "requires": { "has": "^1.0.3" } }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", "dev": true }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "is-docker": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", + "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", "dev": true }, "is-extglob": { @@ -16112,9 +15552,9 @@ "dev": true }, "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", "dev": true }, "is-number": { @@ -16123,10 +15563,16 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, "is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", "dev": true }, "is-path-inside": { @@ -16144,15 +15590,6 @@ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, "is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", @@ -16160,11 +15597,12 @@ "dev": true }, "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", "dev": true, "requires": { + "call-bind": "^1.0.2", "has-symbols": "^1.0.1" } }, @@ -16180,6 +15618,12 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, "is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", @@ -16207,11 +15651,14 @@ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } }, "isarray": { "version": "0.0.1", @@ -16225,12 +15672,6 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -16708,9 +16149,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "lodash.assign": { @@ -16789,21 +16230,6 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, "markdown-table": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", @@ -16990,114 +16416,13 @@ "dev": true }, "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, "miller-rabin": { @@ -17117,26 +16442,18 @@ "dev": true }, "mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", "dev": true }, "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", "dev": true, "requires": { - "mime-db": "1.44.0" - }, - "dependencies": { - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true - } + "mime-db": "1.46.0" } }, "mimic-fn": { @@ -17205,27 +16522,6 @@ "minipass": "^2.9.0" } }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -17244,6 +16540,15 @@ "mkdirp": "*" } }, + "mnemonist": { + "version": "0.38.3", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", + "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", + "dev": true, + "requires": { + "obliterator": "^1.6.1" + } + }, "mocha": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", @@ -17316,6 +16621,13 @@ "locate-path": "^3.0.0" } }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", @@ -17451,25 +16763,6 @@ "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=", "dev": true }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -17665,47 +16958,10 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", "dev": true }, "object-keys": { @@ -17714,15 +16970,6 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, "object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", @@ -17744,23 +16991,21 @@ } }, "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", + "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", "dev": true, "requires": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "es-abstract": "^1.18.0-next.2" } }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } + "obliterator": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz", + "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==", + "dev": true }, "oboe": { "version": "2.1.4", @@ -17797,6 +17042,16 @@ "mimic-fn": "^2.1.0" } }, + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, "opencollective-postinstall": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", @@ -17920,12 +17175,6 @@ "integrity": "sha1-juqz5U+laSD+Fro493+iGqzC104=", "dev": true }, - "parse-code-context": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-code-context/-/parse-code-context-1.0.0.tgz", - "integrity": "sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA==", - "dev": true - }, "parse-headers": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", @@ -17947,26 +17196,21 @@ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, "patch-package": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.2.2.tgz", - "integrity": "sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg==", + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.4.7.tgz", + "integrity": "sha512-S0vh/ZEafZ17hbhgqdnpunKDfzHQibQizx9g8yEf5dcVk3KOflOfdufRXQX8CSEkyOQwuM/bNz1GwKvFj54kaQ==", "dev": true, "requires": { "@yarnpkg/lockfile": "^1.1.0", "chalk": "^2.4.2", "cross-spawn": "^6.0.5", - "find-yarn-workspace-root": "^1.2.1", + "find-yarn-workspace-root": "^2.0.0", "fs-extra": "^7.0.1", "is-ci": "^2.0.0", "klaw-sync": "^6.0.0", "minimist": "^1.2.0", + "open": "^7.4.2", "rimraf": "^2.6.3", "semver": "^5.6.0", "slash": "^2.0.0", @@ -18066,9 +17310,9 @@ } }, "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, "pbkdf2": { @@ -18124,57 +17368,51 @@ } }, "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", "dev": true, "requires": { - "find-up": "^4.0.0" + "find-up": "^5.0.0" }, "dependencies": { "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" } }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -18192,12 +17430,6 @@ "semver-compare": "^1.0.0" } }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, "postinstall-postinstall": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz", @@ -18217,35 +17449,32 @@ "dev": true }, "prettier": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", - "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", "dev": true }, "prettier-plugin-solidity": { - "version": "1.0.0-alpha.60", - "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-alpha.60.tgz", - "integrity": "sha512-Dd6T0dVfw0kJrlEnLDFFE3mKRSP7zpT6zcIWvnSW+z4NBl+gmwJ7UJRZHD0CNDD6N48c+zb28xs3oF0ylDaYyg==", + "version": "1.0.0-beta.6", + "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.6.tgz", + "integrity": "sha512-WymLqd22Hl93t5+HDNLk08TAWp4i4vZMhpihuVqkwOApjCT7mH1qwhLtvf3m+NdU//qj8vrPDmMoT+xc74skcg==", "dev": true, "requires": { - "@solidity-parser/parser": "^0.9.0", + "@solidity-parser/parser": "^0.12.0", "dir-to-object": "^2.0.0", - "emoji-regex": "^9.0.0", + "emoji-regex": "^9.2.1", "escape-string-regexp": "^4.0.0", - "extract-comments": "^1.1.0", - "prettier": "^2.0.5", - "semver": "^7.3.2", + "prettier": "^2.2.1", + "semver": "^7.3.4", + "solidity-comments-extractor": "^0.0.4", "string-width": "^4.2.0" }, "dependencies": { "@solidity-parser/parser": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.9.0.tgz", - "integrity": "sha512-u1WzZgzOBFsGAcUhyj8DN/kop1SvrsaRT2ZVvDpVYnFI86YwbLrXCTGxefJzYGnA5Vajbbhi4aRtlxxFh69dfA==", - "dev": true, - "requires": { - "antlr4": "^4.8.0" - } + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.12.0.tgz", + "integrity": "sha512-DT3f/Aa4tQysZwUsuqBwvr8YRJzKkvPUKV/9o2/o5EVw3xqlbzmtx4O60lTUcZdCawL+N8bBLNUyOGpHjGlJVQ==", + "dev": true }, "ansi-regex": { "version": "5.0.0", @@ -18254,9 +17483,9 @@ "dev": true }, "emoji-regex": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.0.tgz", - "integrity": "sha512-DNc3KFPK18bPdElMJnf/Pkv5TXhxFU3YFDEuGLDRtPmV4rkmCjBkCSEp22u6rBHdSN9Vlp/GK7k98prmE1Jgug==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, "escape-string-regexp": { @@ -18271,16 +17500,28 @@ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { "emoji-regex": "^8.0.0", @@ -18304,6 +17545,12 @@ "requires": { "ansi-regex": "^5.0.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, @@ -18373,9 +17620,9 @@ } }, "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", "dev": true }, "process-nextick-args": { @@ -18452,10 +17699,13 @@ "dev": true }, "qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", - "dev": true + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } }, "query-string": { "version": "5.1.1", @@ -18474,6 +17724,12 @@ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "dev": true }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -18597,28 +17853,6 @@ "minimatch": "3.0.4" } }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, "req-cwd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", @@ -18712,12 +17946,12 @@ "dev": true }, "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { - "is-core-module": "^2.1.0", + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, @@ -18727,12 +17961,6 @@ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", @@ -18742,12 +17970,6 @@ "lowercase-keys": "^1.0.0" } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -18782,10 +18004,13 @@ } }, "run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } }, "rustbn.js": { "version": "0.2.0", @@ -18799,15 +18024,6 @@ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -18815,9 +18031,9 @@ "dev": true }, "sc-istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.5.tgz", - "integrity": "sha512-7wR5EZFLsC4w0wSm9BUuCgW+OGKAU7PNlW5L0qwVPbh+Q1sfVn2fyzfMXYCm6rkNA5ipaCOt94nApcguQwF5Gg==", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz", + "integrity": "sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==", "dev": true, "requires": { "abbrev": "1.0.x", @@ -18891,8 +18107,8 @@ "dev": true }, "scrypt-shim": { - "version": "git+ssh://git@github.com/web3-js/scrypt-shim.git#aafdadda13e660e25e1c525d1f5b2443f5eb1ebb", - "from": "scrypt-shim@github:web3-js/scrypt-shim", + "version": "github:web3-js/scrypt-shim#aafdadda13e660e25e1c525d1f5b2443f5eb1ebb", + "from": "github:web3-js/scrypt-shim", "dev": true, "requires": { "scryptsy": "^2.1.0", @@ -18944,9 +18160,9 @@ "dev": true }, "semver-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", - "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.2.tgz", + "integrity": "sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA==", "dev": true }, "send": { @@ -19026,29 +18242,6 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -19107,6 +18300,17 @@ "rechoir": "^0.6.2" } }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", @@ -19136,140 +18340,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "solc": { "version": "0.6.8", "resolved": "https://registry.npmjs.org/solc/-/solc-0.6.8.tgz", @@ -19340,6 +18410,12 @@ } } }, + "solidity-comments-extractor": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.4.tgz", + "integrity": "sha512-58glBODwXIKMaQ7rfcJOrWtFQMMOK28tJ0/LcB5Xhu7WtAxk4UX2fpgKPuaL41XjMp/y0gAa1MTLqk018wuSzA==", + "dev": true + }, "solidity-coverage": { "version": "0.7.10", "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.10.tgz", @@ -19431,19 +18507,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "source-map-support": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", @@ -19454,12 +18517,6 @@ "source-map": "^0.6.0" } }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, "spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", @@ -19487,20 +18544,11 @@ } }, "spdx-license-ids": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", - "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", "dev": true }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -19549,27 +18597,6 @@ } } }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -19608,79 +18635,23 @@ } }, "string.prototype.trimend": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", - "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", - "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "string_decoder": { @@ -20071,50 +19042,12 @@ "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", "dev": true }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", "dev": true }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -20347,9 +19280,9 @@ } }, "typechain": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-4.0.0.tgz", - "integrity": "sha512-XQUojf02bXyxXNGI0WeCphnh++5eWr9wYH8jm0XqHNv8yENpFrRyX8ffVlkhCnDOOB/jEJJVQytLAOU+Qn0N9Q==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-4.0.3.tgz", + "integrity": "sha512-tmoHQeXZWHxIdeLK+i6dU0CU0vOd9Cndr3jFTZIMzak5/YpFZ8XoiYpTZcngygGBqZo+Z1EUmttLbW9KkFZLgQ==", "dev": true, "requires": { "command-line-args": "^4.0.7", @@ -20357,14 +19290,14 @@ "fs-extra": "^7.0.0", "js-sha3": "^0.8.0", "lodash": "^4.17.15", - "ts-essentials": "^6.0.3", + "ts-essentials": "^7.0.1", "ts-generator": "^0.1.1" }, "dependencies": { "ts-essentials": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-6.0.7.tgz", - "integrity": "sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.1.tgz", + "integrity": "sha512-8lwh3QJtIc1UWhkQtr9XuksXu3O0YQdEE5g79guDfhCaU1FWTDIEDZ1ZSx4HTHUmlJZ8L812j3BZQ4a0aOUkSA==", "dev": true } } @@ -20385,9 +19318,9 @@ } }, "typescript": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", - "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", + "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", "dev": true }, "typical": { @@ -20397,9 +19330,9 @@ "dev": true }, "uglify-js": { - "version": "3.11.6", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.6.tgz", - "integrity": "sha512-oASI1FOJ7BBFkSCNDZ446EgkSuHkOZBuqRFrwXIKWCoXw8ZXQETooTQjkAcBS03Acab7ubCKsXnwuV2svy061g==", + "version": "3.13.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.2.tgz", + "integrity": "sha512-SbMu4D2Vo95LMC/MetNaso1194M1htEA+JrqE9Hk+G2DhI+itfS9TRu9ZKeCahLDNa/J3n4MqUJ/fOHMzQpRWw==", "dev": true, "optional": true }, @@ -20409,6 +19342,18 @@ "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", "dev": true }, + "unbox-primitive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.0.tgz", + "integrity": "sha512-P/51NX+JXyxK/aigg1/ZgyccdAxm5K1+n8+tvqSntjOivPt19gvm1VC49RWYetsiub8WViUchdxl/KWHHB0kzA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.0", + "has-symbols": "^1.0.0", + "which-boxed-primitive": "^1.0.1" + } + }, "unbzip2-stream": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", @@ -20425,18 +19370,6 @@ "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", "dev": true }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -20449,67 +19382,15 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -20549,12 +19430,6 @@ "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", "dev": true }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, "utf8": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", @@ -20568,15 +19443,16 @@ "dev": true }, "util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.1.1.tgz", + "integrity": "sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw==", "dev": true, "requires": { + "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", + "for-each": "^0.3.3", "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" + "object.getownpropertydescriptors": "^2.1.1" } }, "utils-merge": { @@ -20641,9 +19517,9 @@ "dev": true }, "@types/node": { - "version": "12.19.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", - "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", + "version": "12.20.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.6.tgz", + "integrity": "sha512-sRVq8d+ApGslmkE9e3i+D3gFGk7aZHAT+G4cIpIEdLJYPsWiSPwcAnJEjddLQQDqV3Ra2jOclX/Sv6YrvGYiWA==", "dev": true }, "bn.js": { @@ -20714,9 +19590,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", - "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "version": "10.17.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.55.tgz", + "integrity": "sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==", "dev": true }, "elliptic": { @@ -20826,9 +19702,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", - "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "version": "10.17.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.55.tgz", + "integrity": "sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==", "dev": true } } @@ -21125,9 +20001,9 @@ "dev": true }, "@types/node": { - "version": "10.17.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", - "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "version": "10.17.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.55.tgz", + "integrity": "sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==", "dev": true }, "cacheable-request": { @@ -21225,9 +20101,9 @@ }, "dependencies": { "@types/node": { - "version": "12.19.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", - "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", + "version": "12.20.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.6.tgz", + "integrity": "sha512-sRVq8d+ApGslmkE9e3i+D3gFGk7aZHAT+G4cIpIEdLJYPsWiSPwcAnJEjddLQQDqV3Ra2jOclX/Sv6YrvGYiWA==", "dev": true }, "bn.js": { @@ -21461,9 +20337,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.45.tgz", - "integrity": "sha512-a+oe0zGtwRsSDynACia/z1e4gKPNnDhAV3G6GWY6ZNCzaujNCdKC7dE2JFkGHAlUhCRHgXNmWbh417bi9dEXBw==", + "version": "10.17.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.55.tgz", + "integrity": "sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==", "dev": true }, "elliptic": { @@ -21490,18 +20366,18 @@ }, "dependencies": { "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "dev": true, "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "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" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" } } } @@ -21595,7 +20471,7 @@ "eth-lib": "0.2.7", "ethereumjs-common": "^1.3.2", "ethereumjs-tx": "^2.1.1", - "scrypt-shim": "scrypt-shim@github:web3-js/scrypt-shim", + "scrypt-shim": "github:web3-js/scrypt-shim", "underscore": "1.9.1", "uuid": "3.3.2", "web3-core": "1.2.2", @@ -21810,9 +20686,9 @@ }, "dependencies": { "@types/node": { - "version": "12.19.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.5.tgz", - "integrity": "sha512-Wgdl27uw/jUYUFyajUGKSjDNGxmJrZi9sjeG6UJImgUtKbJoO9aldx+1XODN1EpNDX9DirvbvHHmTsNlb8GwMA==", + "version": "12.20.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.6.tgz", + "integrity": "sha512-sRVq8d+ApGslmkE9e3i+D3gFGk7aZHAT+G4cIpIEdLJYPsWiSPwcAnJEjddLQQDqV3Ra2jOclX/Sv6YrvGYiWA==", "dev": true }, "bn.js": { @@ -21925,7 +20801,7 @@ "requires": { "underscore": "1.9.1", "web3-core-helpers": "1.2.2", - "websocket": "websocket@github:web3-js/WebSocket-Node#polyfill/globalThis" + "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" } }, "web3-shh": { @@ -21941,9 +20817,9 @@ } }, "web3-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.0.tgz", - "integrity": "sha512-2mS5axFCbkhicmoDRuJeuo0TVGQDgC2sPi/5dblfVC+PMtX0efrb8Xlttv/eGkq7X4E83Pds34FH98TP2WOUZA==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.4.tgz", + "integrity": "sha512-/vC2v0MaZNpWooJfpRw63u0Y3ag2gNjAWiLtMSL6QQLmCqCy4SQIndMt/vRyx0uMoeGt1YTwSXEcHjUzOhLg0A==", "dev": true, "requires": { "bn.js": "^4.11.9", @@ -21957,8 +20833,8 @@ } }, "websocket": { - "version": "git+ssh://git@github.com/web3-js/WebSocket-Node.git#ef5ea2f41daf4a2113b80c9223df884b4d56c400", - "from": "websocket@github:web3-js/WebSocket-Node#polyfill/globalThis", + "version": "github:web3-js/WebSocket-Node#ef5ea2f41daf4a2113b80c9223df884b4d56c400", + "from": "github:web3-js/WebSocket-Node#polyfill/globalThis", "dev": true, "requires": { "debug": "^2.2.0", @@ -21994,6 +20870,19 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", @@ -22078,18 +20967,18 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", - "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz", + "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==", "dev": true }, "xhr": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", - "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", "dev": true, "requires": { - "global": "~4.3.0", + "global": "~4.4.0", "is-function": "^1.0.1", "parse-headers": "^2.0.0", "xtend": "^4.0.0" @@ -22152,9 +21041,9 @@ } }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", "dev": true }, "yaeti": { @@ -22170,9 +21059,9 @@ "dev": true }, "yaml": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", - "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true }, "yargs": { @@ -22300,6 +21189,12 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } From f9cf541be1932db72fa2a81263d31cbb4890f7e4 Mon Sep 17 00:00:00 2001 From: sendra Date: Tue, 23 Mar 2021 18:52:51 +0100 Subject: [PATCH 178/219] Added incentives data to ui helper --- .../interfaces/IAaveIncentivesController.sol | 15 ++++++ contracts/misc/UiPoolDataProvider.sol | 51 ++++++++++++++++++- .../misc/interfaces/IUiPoolDataProvider.sol | 24 ++++++++- 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/contracts/interfaces/IAaveIncentivesController.sol b/contracts/interfaces/IAaveIncentivesController.sol index c049bd77..5125ac7b 100644 --- a/contracts/interfaces/IAaveIncentivesController.sol +++ b/contracts/interfaces/IAaveIncentivesController.sol @@ -3,9 +3,24 @@ pragma solidity 0.6.12; pragma experimental ABIEncoderV2; interface IAaveIncentivesController { + struct AssetData { + uint128 emissionPerSecond; + uint128 lastUpdateTimestamp; + uint256 index; + } + + function REWARD_TOKEN() external view returns (address rewardToken); + + function assets(address underlying) external view returns (AssetData memory assets); + function handleAction( address user, uint256 userBalance, uint256 totalSupply ) external; + + function getRewardsBalance(address[] calldata assets, address user) + external + view + returns (uint256); } diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 65fdc4dd..4d61ee8d 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -4,6 +4,7 @@ pragma experimental ABIEncoderV2; import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; +import {IAaveIncentivesController} from '../interfaces/IAaveIncentivesController.sol'; import {IUiPoolDataProvider} from './interfaces/IUiPoolDataProvider.sol'; import {ILendingPool} from '../interfaces/ILendingPool.sol'; import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol'; @@ -43,7 +44,11 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ); } - function getReservesData(ILendingPoolAddressesProvider provider, address user) + function getReservesData( + ILendingPoolAddressesProvider provider, + IAaveIncentivesController incentivesControllerAddr, + address user + ) external view override @@ -53,6 +58,8 @@ contract UiPoolDataProvider is IUiPoolDataProvider { uint256 ) { + IAaveIncentivesController incentivesController = + IAaveIncentivesController(incentivesControllerAddr); ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); IPriceOracleGetter oracle = IPriceOracleGetter(provider.getPriceOracle()); address[] memory reserves = lendingPool.getReservesList(); @@ -122,6 +129,11 @@ contract UiPoolDataProvider is IUiPoolDataProvider { DefaultReserveInterestRateStrategy(reserveData.interestRateStrategyAddress) ); + // incentives + reserveData.emissionPerSecond = incentivesController + .assets(reserveData.underlyingAsset) + .emissionPerSecond; + if (user != address(0)) { // user reserve data userReservesData[i].underlyingAsset = reserveData.underlyingAsset; @@ -155,6 +167,43 @@ contract UiPoolDataProvider is IUiPoolDataProvider { } } } + return (reservesData, userReservesData, oracle.getAssetPrice(MOCK_USD_ADDRESS)); } + + function getUserIncentivesBalance( + ILendingPoolAddressesProvider provider, + IAaveIncentivesController incentivesControllerAddr, + address user + ) external view override returns (IncentivesDataUser memory) { + IAaveIncentivesController incentivesController = + IAaveIncentivesController(incentivesControllerAddr); + ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); + IPriceOracleGetter oracle = IPriceOracleGetter(provider.getPriceOracle()); + address[] memory reserves = lendingPool.getReservesList(); + + // array of atokens that have incentives + address[] memory incentivesATokens = new address[](user != address(0) ? reserves.length : 0); + + for (uint256 i = 0; i < reserves.length; i++) { + DataTypes.ReserveData memory baseData = lendingPool.getReserveData(reserves[i]); + if (user != address(0)) { + incentivesATokens[i] = baseData.aTokenAddress; + } + } + + IncentivesDataUser memory userRewardsBalance; + if (user != address(0)) { + userRewardsBalance.rewardToken = incentivesController.REWARD_TOKEN(); + userRewardsBalance.claimableRewards = incentivesController.getRewardsBalance( + incentivesATokens, + user + ); + userRewardsBalance.rewardTokenDecimals = IERC20Detailed(userRewardsBalance.rewardToken) + .decimals(); + userRewardsBalance.rewardTokenPriceEth = oracle.getAssetPrice(userRewardsBalance.rewardToken); + } + + return (userRewardsBalance); + } } diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index 81a553e8..a1fb7572 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -3,6 +3,7 @@ pragma solidity 0.6.12; pragma experimental ABIEncoderV2; import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; +import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; interface IUiPoolDataProvider { struct AggregatedReserveData { @@ -41,7 +42,18 @@ interface IUiPoolDataProvider { uint256 variableRateSlope2; uint256 stableRateSlope1; uint256 stableRateSlope2; + // incentives + uint128 emissionPerSecond; } + + struct IncentivesDataUser { + address rewardToken; + uint256 claimableRewards; + uint256 rewardTokenDecimals; + uint256 rewardTokenPriceEth; + uint128 emissionPerSecond; + } + // // struct ReserveData { // uint256 averageStableBorrowRate; @@ -67,7 +79,11 @@ interface IUiPoolDataProvider { // address aTokenAddress; // } - function getReservesData(ILendingPoolAddressesProvider provider, address user) + function getReservesData( + ILendingPoolAddressesProvider provider, + IAaveIncentivesController incentives, + address user + ) external view returns ( @@ -76,6 +92,12 @@ interface IUiPoolDataProvider { uint256 ); + function getUserIncentivesBalance( + ILendingPoolAddressesProvider provider, + IAaveIncentivesController incentives, + address user + ) external view returns (IncentivesDataUser memory); + // function getUserReservesData(ILendingPoolAddressesProvider provider, address user) // external // view From 83a499f2994a4127d706c0cb5dfa39636ab042b8 Mon Sep 17 00:00:00 2001 From: sendra Date: Fri, 26 Mar 2021 11:08:07 +0100 Subject: [PATCH 179/219] added incentives emission for a / v /s tokens --- contracts/misc/UiPoolDataProvider.sol | 12 ++++++++++-- contracts/misc/interfaces/IUiPoolDataProvider.sol | 4 +++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 4d61ee8d..15c0e91c 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -130,8 +130,16 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ); // incentives - reserveData.emissionPerSecond = incentivesController - .assets(reserveData.underlyingAsset) + reserveData.aEmissionPerSecond = incentivesController + .assets(reserveData.aTokenAddress) + .emissionPerSecond; + + reserveData.vEmissionPerSecond = incentivesController + .assets(reserveData.variableDebtTokenAddress) + .emissionPerSecond; + + reserveData.sEmissionPerSecond = incentivesController + .assets(reserveData.stableDebtTokenAddress) .emissionPerSecond; if (user != address(0)) { diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index a1fb7572..41519611 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -43,7 +43,9 @@ interface IUiPoolDataProvider { uint256 stableRateSlope1; uint256 stableRateSlope2; // incentives - uint128 emissionPerSecond; + uint128 aEmissionPerSecond; + uint128 vEmissionPerSecond; + uint128 sEmissionPerSecond; } struct IncentivesDataUser { From 2028631ad74e89fbdd571a26b38cd6bb25ef2570 Mon Sep 17 00:00:00 2001 From: sendra Date: Fri, 26 Mar 2021 13:59:49 +0100 Subject: [PATCH 180/219] fixed not needed casting --- contracts/misc/UiPoolDataProvider.sol | 4 ---- 1 file changed, 4 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 15c0e91c..aff0c92d 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -58,8 +58,6 @@ contract UiPoolDataProvider is IUiPoolDataProvider { uint256 ) { - IAaveIncentivesController incentivesController = - IAaveIncentivesController(incentivesControllerAddr); ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); IPriceOracleGetter oracle = IPriceOracleGetter(provider.getPriceOracle()); address[] memory reserves = lendingPool.getReservesList(); @@ -184,8 +182,6 @@ contract UiPoolDataProvider is IUiPoolDataProvider { IAaveIncentivesController incentivesControllerAddr, address user ) external view override returns (IncentivesDataUser memory) { - IAaveIncentivesController incentivesController = - IAaveIncentivesController(incentivesControllerAddr); ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); IPriceOracleGetter oracle = IPriceOracleGetter(provider.getPriceOracle()); address[] memory reserves = lendingPool.getReservesList(); From ab8c9a22a912399df402acd8019f028c8cf74f65 Mon Sep 17 00:00:00 2001 From: andyk Date: Fri, 26 Mar 2021 15:06:49 +0200 Subject: [PATCH 181/219] fix typo in incentives controller env --- contracts/misc/UiPoolDataProvider.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index aff0c92d..d9350e6a 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -46,7 +46,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { function getReservesData( ILendingPoolAddressesProvider provider, - IAaveIncentivesController incentivesControllerAddr, + IAaveIncentivesController incentivesController, address user ) external @@ -179,7 +179,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { function getUserIncentivesBalance( ILendingPoolAddressesProvider provider, - IAaveIncentivesController incentivesControllerAddr, + IAaveIncentivesController incentivesController, address user ) external view override returns (IncentivesDataUser memory) { ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); From e81ddb4e2f66039a819183027dafd36bd609965f Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 29 Mar 2021 17:10:35 +0200 Subject: [PATCH 182/219] Added incentives information to UI data provider contract --- .../interfaces/IAaveIncentivesController.sol | 6 ++ contracts/misc/UiPoolDataProvider.sol | 91 +++++++++++-------- .../misc/interfaces/IUiPoolDataProvider.sol | 33 +++++-- 3 files changed, 85 insertions(+), 45 deletions(-) diff --git a/contracts/interfaces/IAaveIncentivesController.sol b/contracts/interfaces/IAaveIncentivesController.sol index 5125ac7b..8e9c74a7 100644 --- a/contracts/interfaces/IAaveIncentivesController.sol +++ b/contracts/interfaces/IAaveIncentivesController.sol @@ -11,6 +11,8 @@ interface IAaveIncentivesController { function REWARD_TOKEN() external view returns (address rewardToken); + function PRECISION() external view returns (uint8); + function assets(address underlying) external view returns (AssetData memory assets); function handleAction( @@ -23,4 +25,8 @@ interface IAaveIncentivesController { external view returns (uint256); + + function getUserUnclaimedRewards(address _user) external view returns (uint256); + + function getUserAssetData(address user, address asset) external view returns (uint256); } diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index aff0c92d..28b0da0b 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -46,7 +46,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { function getReservesData( ILendingPoolAddressesProvider provider, - IAaveIncentivesController incentivesControllerAddr, + IAaveIncentivesController incentivesController, address user ) external @@ -55,7 +55,8 @@ contract UiPoolDataProvider is IUiPoolDataProvider { returns ( AggregatedReserveData[] memory, UserReserveData[] memory, - uint256 + uint256, + IncentivesDataUser memory ) { ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); @@ -128,19 +129,54 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ); // incentives + // IncentivesAssetData memory aTokenIncentives = incentivesController.assets(reserveData.aTokenAddress); reserveData.aEmissionPerSecond = incentivesController .assets(reserveData.aTokenAddress) .emissionPerSecond; + reserveData.aIncentivesLastUpdateTimestamp = incentivesController + .assets(reserveData.aTokenAddress) + .lastUpdateTimestamp; + reserveData.aTokenIncentivesIndex = incentivesController + .assets(reserveData.aTokenAddress) + .index; - reserveData.vEmissionPerSecond = incentivesController - .assets(reserveData.variableDebtTokenAddress) - .emissionPerSecond; - + // IncentivesAssetData memory sTokenIncentives = incentivesController.assets(reserveData.stableDebtTokenAddress); reserveData.sEmissionPerSecond = incentivesController .assets(reserveData.stableDebtTokenAddress) .emissionPerSecond; + reserveData.sIncentivesLastUpdateTimestamp = incentivesController + .assets(reserveData.stableDebtTokenAddress) + .lastUpdateTimestamp; + reserveData.sTokenIncentivesIndex = incentivesController + .assets(reserveData.stableDebtTokenAddress) + .index; + + // IncentivesAssetData memory vTokenIncentives = incentivesController.assets(reserveData.variableDebtTokenAddress); + reserveData.vEmissionPerSecond = incentivesController + .assets(reserveData.variableDebtTokenAddress) + .emissionPerSecond; + reserveData.vIncentivesLastUpdateTimestamp = incentivesController + .assets(reserveData.variableDebtTokenAddress) + .lastUpdateTimestamp; + reserveData.vTokenIncentivesIndex = incentivesController + .assets(reserveData.variableDebtTokenAddress) + .index; if (user != address(0)) { + // incentives + // userIncentives.incentivesLastUpdated = + userReservesData[i].aTokenincentivesUserIndex = incentivesController.getUserAssetData( + user, + reserveData.aTokenAddress + ); + userReservesData[i].sTokenincentivesUserIndex = incentivesController.getUserAssetData( + user, + reserveData.stableDebtTokenAddress + ); + userReservesData[i].vTokenincentivesUserIndex = incentivesController.getUserAssetData( + user, + reserveData.variableDebtTokenAddress + ); // user reserve data userReservesData[i].underlyingAsset = reserveData.underlyingAsset; userReservesData[i].scaledATokenBalance = IAToken(reserveData.aTokenAddress) @@ -174,40 +210,21 @@ contract UiPoolDataProvider is IUiPoolDataProvider { } } - return (reservesData, userReservesData, oracle.getAssetPrice(MOCK_USD_ADDRESS)); - } - - function getUserIncentivesBalance( - ILendingPoolAddressesProvider provider, - IAaveIncentivesController incentivesControllerAddr, - address user - ) external view override returns (IncentivesDataUser memory) { - ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); - IPriceOracleGetter oracle = IPriceOracleGetter(provider.getPriceOracle()); - address[] memory reserves = lendingPool.getReservesList(); - - // array of atokens that have incentives - address[] memory incentivesATokens = new address[](user != address(0) ? reserves.length : 0); - - for (uint256 i = 0; i < reserves.length; i++) { - DataTypes.ReserveData memory baseData = lendingPool.getReserveData(reserves[i]); - if (user != address(0)) { - incentivesATokens[i] = baseData.aTokenAddress; - } - } - - IncentivesDataUser memory userRewardsBalance; + IncentivesDataUser memory incentivesDataUser; if (user != address(0)) { - userRewardsBalance.rewardToken = incentivesController.REWARD_TOKEN(); - userRewardsBalance.claimableRewards = incentivesController.getRewardsBalance( - incentivesATokens, - user - ); - userRewardsBalance.rewardTokenDecimals = IERC20Detailed(userRewardsBalance.rewardToken) + incentivesDataUser.userUnclaimedRewards = incentivesController.getUserUnclaimedRewards(user); + incentivesDataUser.rewardToken = incentivesController.REWARD_TOKEN(); + incentivesDataUser.precision = incentivesController.PRECISION(); + incentivesDataUser.rewardTokenDecimals = IERC20Detailed(incentivesDataUser.rewardToken) .decimals(); - userRewardsBalance.rewardTokenPriceEth = oracle.getAssetPrice(userRewardsBalance.rewardToken); + incentivesDataUser.rewardTokenPriceEth = oracle.getAssetPrice(incentivesDataUser.rewardToken); } - return (userRewardsBalance); + return ( + reservesData, + userReservesData, + oracle.getAssetPrice(MOCK_USD_ADDRESS), + incentivesDataUser + ); } } diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index 41519611..9ad0c8c4 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -46,14 +46,20 @@ interface IUiPoolDataProvider { uint128 aEmissionPerSecond; uint128 vEmissionPerSecond; uint128 sEmissionPerSecond; + uint256 aIncentivesLastUpdateTimestamp; + uint256 vIncentivesLastUpdateTimestamp; + uint256 sIncentivesLastUpdateTimestamp; + uint256 aTokenIncentivesIndex; + uint256 vTokenIncentivesIndex; + uint256 sTokenIncentivesIndex; } struct IncentivesDataUser { address rewardToken; - uint256 claimableRewards; + uint256 userUnclaimedRewards; uint256 rewardTokenDecimals; uint256 rewardTokenPriceEth; - uint128 emissionPerSecond; + uint8 precision; } // @@ -70,6 +76,16 @@ interface IUiPoolDataProvider { uint256 scaledVariableDebt; uint256 principalStableDebt; uint256 stableBorrowLastUpdateTimestamp; + // incentives + uint256 aTokenincentivesUserIndex; + uint256 vTokenincentivesUserIndex; + uint256 sTokenincentivesUserIndex; + } + + struct IncentivesAssetData { + uint128 emissionPerSecond; + uint128 lastUpdateTimestamp; + uint256 index; } // @@ -91,14 +107,15 @@ interface IUiPoolDataProvider { returns ( AggregatedReserveData[] memory, UserReserveData[] memory, - uint256 + uint256, + IncentivesDataUser memory ); - function getUserIncentivesBalance( - ILendingPoolAddressesProvider provider, - IAaveIncentivesController incentives, - address user - ) external view returns (IncentivesDataUser memory); + // function getUserIncentivesBalance( + // ILendingPoolAddressesProvider provider, + // IAaveIncentivesController incentives, + // address user + // ) external view returns (IncentivesDataUser memory); // function getUserReservesData(ILendingPoolAddressesProvider provider, address user) // external From 99a0d17de4508abeeb67cca681180b6c9f695e42 Mon Sep 17 00:00:00 2001 From: sendra Date: Tue, 30 Mar 2021 12:39:00 +0200 Subject: [PATCH 183/219] reused local vars to not fill stack --- contracts/misc/UiPoolDataProvider.sol | 66 ++++++++----------- .../misc/interfaces/IUiPoolDataProvider.sol | 48 +------------- 2 files changed, 32 insertions(+), 82 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 28b0da0b..d585593c 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -25,6 +25,21 @@ contract UiPoolDataProvider is IUiPoolDataProvider { using UserConfiguration for DataTypes.UserConfigurationMap; address public constant MOCK_USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96; + IAaveIncentivesController immutable incentivesController; + IPriceOracleGetter immutable oracle; + + constructor(IAaveIncentivesController _incentivesController, IPriceOracleGetter _oracle) public { + incentivesController = _incentivesController; + oracle = _oracle; + } + + function getPriceOracle() public view override returns (address) { + return address(oracle); + } + + function getIncentivesController() public view override returns (address) { + return address(incentivesController); + } function getInterestRateStrategySlopes(DefaultReserveInterestRateStrategy interestRateStrategy) internal @@ -44,11 +59,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ); } - function getReservesData( - ILendingPoolAddressesProvider provider, - IAaveIncentivesController incentivesController, - address user - ) + function getReservesData(ILendingPoolAddressesProvider provider, address user) external view override @@ -60,7 +71,6 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ) { ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); - IPriceOracleGetter oracle = IPriceOracleGetter(provider.getPriceOracle()); address[] memory reserves = lendingPool.getReservesList(); DataTypes.UserConfigurationMap memory userConfig = lendingPool.getUserConfiguration(user); @@ -129,42 +139,24 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ); // incentives - // IncentivesAssetData memory aTokenIncentives = incentivesController.assets(reserveData.aTokenAddress); - reserveData.aEmissionPerSecond = incentivesController - .assets(reserveData.aTokenAddress) - .emissionPerSecond; - reserveData.aIncentivesLastUpdateTimestamp = incentivesController - .assets(reserveData.aTokenAddress) - .lastUpdateTimestamp; - reserveData.aTokenIncentivesIndex = incentivesController - .assets(reserveData.aTokenAddress) - .index; + IAaveIncentivesController.AssetData memory tokenIncentivesInfo = + incentivesController.assets(reserveData.aTokenAddress); + reserveData.aEmissionPerSecond = tokenIncentivesInfo.emissionPerSecond; + reserveData.aIncentivesLastUpdateTimestamp = tokenIncentivesInfo.lastUpdateTimestamp; + reserveData.aTokenIncentivesIndex = tokenIncentivesInfo.index; - // IncentivesAssetData memory sTokenIncentives = incentivesController.assets(reserveData.stableDebtTokenAddress); - reserveData.sEmissionPerSecond = incentivesController - .assets(reserveData.stableDebtTokenAddress) - .emissionPerSecond; - reserveData.sIncentivesLastUpdateTimestamp = incentivesController - .assets(reserveData.stableDebtTokenAddress) - .lastUpdateTimestamp; - reserveData.sTokenIncentivesIndex = incentivesController - .assets(reserveData.stableDebtTokenAddress) - .index; + tokenIncentivesInfo = incentivesController.assets(reserveData.stableDebtTokenAddress); + reserveData.sEmissionPerSecond = tokenIncentivesInfo.emissionPerSecond; + reserveData.sIncentivesLastUpdateTimestamp = tokenIncentivesInfo.lastUpdateTimestamp; + reserveData.sTokenIncentivesIndex = tokenIncentivesInfo.index; - // IncentivesAssetData memory vTokenIncentives = incentivesController.assets(reserveData.variableDebtTokenAddress); - reserveData.vEmissionPerSecond = incentivesController - .assets(reserveData.variableDebtTokenAddress) - .emissionPerSecond; - reserveData.vIncentivesLastUpdateTimestamp = incentivesController - .assets(reserveData.variableDebtTokenAddress) - .lastUpdateTimestamp; - reserveData.vTokenIncentivesIndex = incentivesController - .assets(reserveData.variableDebtTokenAddress) - .index; + tokenIncentivesInfo = incentivesController.assets(reserveData.variableDebtTokenAddress); + reserveData.vEmissionPerSecond = tokenIncentivesInfo.emissionPerSecond; + reserveData.vIncentivesLastUpdateTimestamp = tokenIncentivesInfo.lastUpdateTimestamp; + reserveData.vTokenIncentivesIndex = tokenIncentivesInfo.index; if (user != address(0)) { // incentives - // userIncentives.incentivesLastUpdated = userReservesData[i].aTokenincentivesUserIndex = incentivesController.getUserAssetData( user, reserveData.aTokenAddress diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index 9ad0c8c4..3bdad9f6 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -62,12 +62,6 @@ interface IUiPoolDataProvider { uint8 precision; } - // - // struct ReserveData { - // uint256 averageStableBorrowRate; - // uint256 totalLiquidity; - // } - struct UserReserveData { address underlyingAsset; uint256 scaledATokenBalance; @@ -82,26 +76,7 @@ interface IUiPoolDataProvider { uint256 sTokenincentivesUserIndex; } - struct IncentivesAssetData { - uint128 emissionPerSecond; - uint128 lastUpdateTimestamp; - uint256 index; - } - - // - // struct ATokenSupplyData { - // string name; - // string symbol; - // uint8 decimals; - // uint256 totalSupply; - // address aTokenAddress; - // } - - function getReservesData( - ILendingPoolAddressesProvider provider, - IAaveIncentivesController incentives, - address user - ) + function getReservesData(ILendingPoolAddressesProvider provider, address user) external view returns ( @@ -111,24 +86,7 @@ interface IUiPoolDataProvider { IncentivesDataUser memory ); - // function getUserIncentivesBalance( - // ILendingPoolAddressesProvider provider, - // IAaveIncentivesController incentives, - // address user - // ) external view returns (IncentivesDataUser memory); + function getPriceOracle() external view returns (address); - // function getUserReservesData(ILendingPoolAddressesProvider provider, address user) - // external - // view - // returns (UserReserveData[] memory); - // - // function getAllATokenSupply(ILendingPoolAddressesProvider provider) - // external - // view - // returns (ATokenSupplyData[] memory); - // - // function getATokenSupply(address[] calldata aTokens) - // external - // view - // returns (ATokenSupplyData[] memory); + function getIncentivesController() external view returns (address); } From 9ed357662bdecb7989da044c52846543786e9090 Mon Sep 17 00:00:00 2001 From: sendra Date: Tue, 30 Mar 2021 12:42:20 +0200 Subject: [PATCH 184/219] added public to incentives controller and price oracle so we can remove getters --- contracts/misc/UiPoolDataProvider.sol | 12 ++---------- contracts/misc/interfaces/IUiPoolDataProvider.sol | 4 ---- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index d585593c..d0b71a17 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -25,22 +25,14 @@ contract UiPoolDataProvider is IUiPoolDataProvider { using UserConfiguration for DataTypes.UserConfigurationMap; address public constant MOCK_USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96; - IAaveIncentivesController immutable incentivesController; - IPriceOracleGetter immutable oracle; + IAaveIncentivesController public immutable incentivesController; + IPriceOracleGetter public immutable oracle; constructor(IAaveIncentivesController _incentivesController, IPriceOracleGetter _oracle) public { incentivesController = _incentivesController; oracle = _oracle; } - function getPriceOracle() public view override returns (address) { - return address(oracle); - } - - function getIncentivesController() public view override returns (address) { - return address(incentivesController); - } - function getInterestRateStrategySlopes(DefaultReserveInterestRateStrategy interestRateStrategy) internal view diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index 3bdad9f6..240f9fd4 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -85,8 +85,4 @@ interface IUiPoolDataProvider { uint256, IncentivesDataUser memory ); - - function getPriceOracle() external view returns (address); - - function getIncentivesController() external view returns (address); } From 516cbc7349065bcea1f9d9e68810b12428ed3b36 Mon Sep 17 00:00:00 2001 From: sendra Date: Tue, 30 Mar 2021 13:17:08 +0200 Subject: [PATCH 185/219] updated deployment scripts --- helpers/contracts-deployments.ts | 26 +++++++++++++- package.json | 4 ++- .../deployments/deploy-UiPoolDataProvider.ts | 36 +++++++++++++------ 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 07f34a91..68024d2a 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -55,12 +55,28 @@ import { registerContractInJsonDb, linkBytecode, insertContractAddressInDb, + deployContract, } 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'; +import { UiPoolDataProvider } from '../types'; +import { verifyContract } from './etherscan-verification'; + +export const deployUiPoolDataProvider = async ( + [incentivesController, aaveOracle]: [tEthereumAddress, tEthereumAddress], + verify?: boolean +) => { + const id = eContractid.UiPoolDataProvider; + const args: string[] = [incentivesController, aaveOracle]; + const instance = await deployContract(id, args); + if (verify) { + await verifyContract(instance.address, args); + } + return instance; +}; const readArtifact = async (id: string) => { if (DRE.network.name === eEthereumNetwork.buidlerevm) { @@ -546,7 +562,15 @@ export const deployMockVariableDebtToken = async ( }; export const deployMockAToken = async ( - args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string, string], + args: [ + tEthereumAddress, + tEthereumAddress, + tEthereumAddress, + tEthereumAddress, + string, + string, + string + ], verify?: boolean ) => { const instance = await withSaveAndVerify( diff --git a/package.json b/package.json index 4532f6fa..dce53f5d 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,9 @@ "print-contracts:kovan": "npm run hardhat:kovan -- print-contracts", "print-contracts:main": "npm run hardhat:main -- print-contracts", "print-contracts:ropsten": "npm run hardhat:main -- print-contracts", - "dev:deployUIProvider": "npm run hardhat:kovan deploy-UiPoolDataProvider", + "dev:deployUIProvider": "hardhat --network kovan deploy-UiPoolDataProvider", + "main:deployUIProvider": "hardhat --network main deploy-UiPoolDataProvider", + "matic:deployUIProvider": "hardhat --network matic deploy-UiPoolDataProvider", "dev:deployUniswapRepayAdapter": "hardhat --network kovan deploy-UniswapRepayAdapter --provider 0x88757f2f99175387aB4C6a4b3067c77A695b0349 --router 0xfcd87315f0e4067070ade8682fcdbc3006631441 --weth 0xd0a1e359811322d97991e03f863a0c30c2cf029c", "dev:UniswapLiquiditySwapAdapter": "hardhat --network kovan deploy-UniswapLiquiditySwapAdapter --provider 0x88757f2f99175387aB4C6a4b3067c77A695b0349 --router 0xfcd87315f0e4067070ade8682fcdbc3006631441 --weth 0xd0a1e359811322d97991e03f863a0c30c2cf029c", "main:deployUniswapRepayAdapter": "hardhat --network main deploy-UniswapRepayAdapter --provider 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 --router 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D --weth 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", diff --git a/tasks/deployments/deploy-UiPoolDataProvider.ts b/tasks/deployments/deploy-UiPoolDataProvider.ts index 2d696702..64a6dae4 100644 --- a/tasks/deployments/deploy-UiPoolDataProvider.ts +++ b/tasks/deployments/deploy-UiPoolDataProvider.ts @@ -1,8 +1,6 @@ import { task } from 'hardhat/config'; - -import { UiPoolDataProviderFactory } from '../../types'; -import { verifyContract } from '../../helpers/etherscan-verification'; -import { eContractid } from '../../helpers/types'; +import { eContractid, eEthereumNetwork, ePolygonNetwork } from '../../helpers/types'; +import { deployUiPoolDataProvider } from '../../helpers/contracts-deployments'; task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider contract`) .addFlag('verify', 'Verify UiPoolDataProvider contract via Etherscan API.') @@ -13,15 +11,31 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider throw new Error('INVALID_CHAIN_ID'); } + const addressesByNetwork = { + // [eEthereumNetwork.kovan]: { + // incentivesController: '', + // aaveOracle: '', + // }, + // [eEthereumNetwork.main]: { + // incentivesController: '', + // aaveOracle: '0xa50ba011c48153de246e5192c8f9258a2ba79ca9', + // }, + [ePolygonNetwork.matic]: { + incentivesController: '0x357D51124f59836DeD84c8a1730D72B749d8BC23', + aaveOracle: '0x21451bD7b528896B4AB2b9764b521D6ed641708d', + }, + }; + console.log(`\n- UiPoolDataProvider deployment`); console.log(`\tDeploying UiPoolDataProvider implementation ...`); - const uiPoolDataProvider = await new UiPoolDataProviderFactory( - await localBRE.ethers.provider.getSigner() - ).deploy(); - await uiPoolDataProvider.deployTransaction.wait(); - console.log('uiPoolDataProvider.address', uiPoolDataProvider.address); - await verifyContract(uiPoolDataProvider.address, []); + const UiPoolDataProvider = await deployUiPoolDataProvider( + [ + addressesByNetwork[localBRE.network.name].incentivesController, + addressesByNetwork[localBRE.network.name].aaveOracle, + ], + verify + ); - console.log(`\tFinished UiPoolDataProvider proxy and implementation deployment`); + console.log(`\tFinished UiPoolDataProvider deployment: ${UiPoolDataProvider.address}`); }); From 5ba17aa1c1745d48379a48a072a0c613386195ea Mon Sep 17 00:00:00 2001 From: sendra Date: Tue, 30 Mar 2021 13:19:47 +0200 Subject: [PATCH 186/219] naming changed to IncentivesUserData --- contracts/misc/UiPoolDataProvider.sol | 16 ++++++++-------- .../misc/interfaces/IUiPoolDataProvider.sol | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index d0b71a17..49bbf63f 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -59,7 +59,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { AggregatedReserveData[] memory, UserReserveData[] memory, uint256, - IncentivesDataUser memory + IncentivesUserData memory ) { ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); @@ -194,21 +194,21 @@ contract UiPoolDataProvider is IUiPoolDataProvider { } } - IncentivesDataUser memory incentivesDataUser; + IncentivesUserData memory incentivesUserData; if (user != address(0)) { - incentivesDataUser.userUnclaimedRewards = incentivesController.getUserUnclaimedRewards(user); - incentivesDataUser.rewardToken = incentivesController.REWARD_TOKEN(); - incentivesDataUser.precision = incentivesController.PRECISION(); - incentivesDataUser.rewardTokenDecimals = IERC20Detailed(incentivesDataUser.rewardToken) + incentivesUserData.userUnclaimedRewards = incentivesController.getUserUnclaimedRewards(user); + incentivesUserData.rewardToken = incentivesController.REWARD_TOKEN(); + incentivesUserData.precision = incentivesController.PRECISION(); + incentivesUserData.rewardTokenDecimals = IERC20Detailed(incentivesUserData.rewardToken) .decimals(); - incentivesDataUser.rewardTokenPriceEth = oracle.getAssetPrice(incentivesDataUser.rewardToken); + incentivesUserData.rewardTokenPriceEth = oracle.getAssetPrice(incentivesUserData.rewardToken); } return ( reservesData, userReservesData, oracle.getAssetPrice(MOCK_USD_ADDRESS), - incentivesDataUser + incentivesUserData ); } } diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index 240f9fd4..efee35bc 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -54,7 +54,7 @@ interface IUiPoolDataProvider { uint256 sTokenIncentivesIndex; } - struct IncentivesDataUser { + struct IncentivesUserData { address rewardToken; uint256 userUnclaimedRewards; uint256 rewardTokenDecimals; @@ -83,6 +83,6 @@ interface IUiPoolDataProvider { AggregatedReserveData[] memory, UserReserveData[] memory, uint256, - IncentivesDataUser memory + IncentivesUserData memory ); } From b84a486d106fe67c9d1019a71132c26527fd789c Mon Sep 17 00:00:00 2001 From: sendra Date: Tue, 6 Apr 2021 16:17:04 +0200 Subject: [PATCH 187/219] removed extra external calls that are not needed --- contracts/misc/UiPoolDataProvider.sol | 3 --- contracts/misc/interfaces/IUiPoolDataProvider.sol | 2 -- 2 files changed, 5 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 49bbf63f..1672ab1a 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -198,9 +198,6 @@ contract UiPoolDataProvider is IUiPoolDataProvider { if (user != address(0)) { incentivesUserData.userUnclaimedRewards = incentivesController.getUserUnclaimedRewards(user); incentivesUserData.rewardToken = incentivesController.REWARD_TOKEN(); - incentivesUserData.precision = incentivesController.PRECISION(); - incentivesUserData.rewardTokenDecimals = IERC20Detailed(incentivesUserData.rewardToken) - .decimals(); incentivesUserData.rewardTokenPriceEth = oracle.getAssetPrice(incentivesUserData.rewardToken); } diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index efee35bc..7757a4f1 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -57,9 +57,7 @@ interface IUiPoolDataProvider { struct IncentivesUserData { address rewardToken; uint256 userUnclaimedRewards; - uint256 rewardTokenDecimals; uint256 rewardTokenPriceEth; - uint8 precision; } struct UserReserveData { From 94a8b0134e784c71e9b286f41aaa900ba7c89d95 Mon Sep 17 00:00:00 2001 From: Jared T Nielsen Date: Tue, 6 Apr 2021 14:08:17 -0700 Subject: [PATCH 188/219] Fix example import in README Fix the interface example. 1) '0' should be 0 2) function needs visibility modifier --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 154b43b4..2ccc518d 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,8 @@ import {ILendingPool} from "@aave/protocol-v2/contracts/interfaces/ILendingPool. contract Misc { - function deposit(address pool, address token, address user, uint256 amount) { - ILendingPool(pool).deposit(token, amount, user, '0'); + function deposit(address pool, address token, address user, uint256 amount) public { + ILendingPool(pool).deposit(token, amount, user, 0); {...} } } From dc2943f2ec243ae93178913fc130c7570d5c5936 Mon Sep 17 00:00:00 2001 From: sendra Date: Wed, 7 Apr 2021 17:44:29 +0200 Subject: [PATCH 189/219] removed incentives data, as it is hardcoded on client side --- contracts/misc/UiPoolDataProvider.sol | 17 ++--------------- .../misc/interfaces/IUiPoolDataProvider.sol | 9 +-------- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 1672ab1a..026d67d9 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -58,8 +58,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { returns ( AggregatedReserveData[] memory, UserReserveData[] memory, - uint256, - IncentivesUserData memory + uint256 ) { ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); @@ -194,18 +193,6 @@ contract UiPoolDataProvider is IUiPoolDataProvider { } } - IncentivesUserData memory incentivesUserData; - if (user != address(0)) { - incentivesUserData.userUnclaimedRewards = incentivesController.getUserUnclaimedRewards(user); - incentivesUserData.rewardToken = incentivesController.REWARD_TOKEN(); - incentivesUserData.rewardTokenPriceEth = oracle.getAssetPrice(incentivesUserData.rewardToken); - } - - return ( - reservesData, - userReservesData, - oracle.getAssetPrice(MOCK_USD_ADDRESS), - incentivesUserData - ); + return (reservesData, userReservesData, oracle.getAssetPrice(MOCK_USD_ADDRESS)); } } diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index 7757a4f1..283c3500 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -54,12 +54,6 @@ interface IUiPoolDataProvider { uint256 sTokenIncentivesIndex; } - struct IncentivesUserData { - address rewardToken; - uint256 userUnclaimedRewards; - uint256 rewardTokenPriceEth; - } - struct UserReserveData { address underlyingAsset; uint256 scaledATokenBalance; @@ -80,7 +74,6 @@ interface IUiPoolDataProvider { returns ( AggregatedReserveData[] memory, UserReserveData[] memory, - uint256, - IncentivesUserData memory + uint256 ); } From 15d556613898f086797486964898d0f929190242 Mon Sep 17 00:00:00 2001 From: wenzhenxiang <308260887@qq.com> Date: Thu, 8 Apr 2021 18:58:38 +0800 Subject: [PATCH 190/219] fix deploy new asset bug fix deploy new asset bug --- tasks/helpers/deploy-new-asset.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tasks/helpers/deploy-new-asset.ts b/tasks/helpers/deploy-new-asset.ts index 03d102c4..718b6372 100644 --- a/tasks/helpers/deploy-new-asset.ts +++ b/tasks/helpers/deploy-new-asset.ts @@ -82,12 +82,12 @@ WRONG RESERVE ASSET SETUP: const rates = await deployDefaultReserveInterestRateStrategy( [ addressProvider.address, - strategyParams.optimalUtilizationRate, - strategyParams.baseVariableBorrowRate, - strategyParams.variableRateSlope1, - strategyParams.variableRateSlope2, - strategyParams.stableRateSlope1, - strategyParams.stableRateSlope2, + strategyParams.strategy.optimalUtilizationRate, + strategyParams.strategy.baseVariableBorrowRate, + strategyParams.strategy.variableRateSlope1, + strategyParams.strategy.variableRateSlope2, + strategyParams.strategy.stableRateSlope1, + strategyParams.strategy.stableRateSlope2, ], verify ); From 717bb133e100236d728fd463704fd0cb4e710815 Mon Sep 17 00:00:00 2001 From: sendra Date: Thu, 8 Apr 2021 13:55:01 +0200 Subject: [PATCH 191/219] added unclaimed user rewards --- contracts/misc/UiPoolDataProvider.sol | 8 +++++++- contracts/misc/interfaces/IUiPoolDataProvider.sol | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 026d67d9..7d2aef55 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -58,6 +58,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { returns ( AggregatedReserveData[] memory, UserReserveData[] memory, + uint256, uint256 ) { @@ -193,6 +194,11 @@ contract UiPoolDataProvider is IUiPoolDataProvider { } } - return (reservesData, userReservesData, oracle.getAssetPrice(MOCK_USD_ADDRESS)); + return ( + reservesData, + userReservesData, + oracle.getAssetPrice(MOCK_USD_ADDRESS), + incentivesController.getUserUnclaimedRewards(user) + ); } } diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index 283c3500..43e4e997 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -74,6 +74,7 @@ interface IUiPoolDataProvider { returns ( AggregatedReserveData[] memory, UserReserveData[] memory, + uint256, uint256 ); } From a5ab0a6e3b3b4715ff692740ae9b68fe2d407ab5 Mon Sep 17 00:00:00 2001 From: sendra Date: Fri, 9 Apr 2021 10:57:01 +0200 Subject: [PATCH 192/219] added mumbai addresses --- package-lock.json | 313 +++++++++--------- package.json | 1 + .../deployments/deploy-UiPoolDataProvider.ts | 6 +- 3 files changed, 171 insertions(+), 149 deletions(-) diff --git a/package-lock.json b/package-lock.json index b05b76cb..cf9af765 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2803,7 +2803,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -5151,8 +5150,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -5889,36 +5887,6 @@ "@ethersproject/strings": ">=5.0.0-beta.130" } }, - "@ethersproject/abstract-provider": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.8.tgz", - "integrity": "sha512-fqJXkewcGdi8LogKMgRyzc/Ls2js07yor7+g9KfPs09uPOcQLg7cc34JN+lk34HH9gg2HU0DIA5797ZR8znkfw==", - "dev": true, - "optional": true, - "requires": { - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/networks": "^5.0.7", - "@ethersproject/properties": "^5.0.7", - "@ethersproject/transactions": "^5.0.9", - "@ethersproject/web": "^5.0.12" - } - }, - "@ethersproject/abstract-signer": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.10.tgz", - "integrity": "sha512-irx7kH7FDAeW7QChDPW19WsxqeB1d3XLyOLSXm0bfPqL1SS07LXWltBJUBUxqC03ORpAOcM3JQj57DU8JnVY2g==", - "dev": true, - "optional": true, - "requires": { - "@ethersproject/abstract-provider": "^5.0.8", - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/properties": "^5.0.7" - } - }, "@ethersproject/address": { "version": "5.0.9", "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.9.tgz", @@ -5933,16 +5901,6 @@ "@ethersproject/rlp": "^5.0.7" } }, - "@ethersproject/base64": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.7.tgz", - "integrity": "sha512-S5oh5DVfCo06xwJXT8fQC68mvJfgScTl2AXvbYMsHNfIBTDb084Wx4iA9MNlEReOv6HulkS+gyrUM/j3514rSw==", - "dev": true, - "optional": true, - "requires": { - "@ethersproject/bytes": "^5.0.9" - } - }, "@ethersproject/bignumber": { "version": "5.0.13", "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.13.tgz", @@ -6010,16 +5968,6 @@ "dev": true, "optional": true }, - "@ethersproject/networks": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.7.tgz", - "integrity": "sha512-dI14QATndIcUgcCBL1c5vUr/YsI5cCHLN81rF7PU+yS7Xgp2/Rzbr9+YqpC6NBXHFUASjh6GpKqsVMpufAL0BQ==", - "dev": true, - "optional": true, - "requires": { - "@ethersproject/logger": "^5.0.8" - } - }, "@ethersproject/properties": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.7.tgz", @@ -6084,20 +6032,6 @@ "@ethersproject/signing-key": "^5.0.8" } }, - "@ethersproject/web": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.12.tgz", - "integrity": "sha512-gVxS5iW0bgidZ76kr7LsTxj4uzN5XpCLzvZrLp8TP+4YgxHfCeetFyQkRPgBEAJdNrexdSBayvyJvzGvOq0O8g==", - "dev": true, - "optional": true, - "requires": { - "@ethersproject/base64": "^5.0.7", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/properties": "^5.0.7", - "@ethersproject/strings": "^5.0.8" - } - }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -7294,15 +7228,6 @@ "requires": { "bn.js": "^5.0.0", "randombytes": "^2.0.1" - }, - "dependencies": { - "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true, - "optional": true - } } }, "browserify-sign": { @@ -7410,6 +7335,14 @@ "dev": true, "requires": { "node-gyp-build": "^4.2.0" + }, + "dependencies": { + "node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "dev": true + } } }, "bytes": { @@ -7510,16 +7443,6 @@ } } }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, "caniuse-lite": { "version": "1.0.30001174", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001174.tgz", @@ -8038,7 +7961,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -8264,7 +8186,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -10434,8 +10355,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -10443,17 +10363,6 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "get-intrinsic": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", - "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, "get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -10501,6 +10410,14 @@ "requires": { "min-document": "^2.19.0", "process": "^0.11.10" + }, + "dependencies": { + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", + "dev": true + } } }, "got": { @@ -10561,7 +10478,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -10599,8 +10515,7 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" }, "has-to-string-tag-x": { "version": "1.4.1", @@ -10873,8 +10788,7 @@ "is-callable": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" }, "is-ci": { "version": "2.0.0", @@ -10897,8 +10811,7 @@ "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" }, "is-descriptor": { "version": "1.0.2", @@ -10947,8 +10860,7 @@ "is-negative-zero": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==" }, "is-object": { "version": "1.0.2", @@ -10977,7 +10889,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -10993,7 +10904,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -11836,8 +11746,7 @@ "object-inspect": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", - "dev": true + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==" }, "object-is": { "version": "1.1.4", @@ -11847,13 +11756,33 @@ "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object-visit": { "version": "1.0.1", @@ -11868,12 +11797,32 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3", "has-symbols": "^1.0.1", "object-keys": "^1.1.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "object.getownpropertydescriptors": { @@ -12145,12 +12094,6 @@ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -12411,22 +12354,71 @@ }, "dependencies": { "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" + }, + "dependencies": { + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true + }, + "is-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + } } } } @@ -12514,6 +12506,15 @@ "uuid": "^3.3.2" } }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -13172,13 +13173,34 @@ "call-bind": "^1.0.0", "define-properties": "^1.1.3", "es-abstract": "^1.18.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "string.prototype.trimend": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", - "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" @@ -13188,7 +13210,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", - "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" @@ -13375,15 +13396,6 @@ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", "dev": true - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } } } }, @@ -13745,6 +13757,14 @@ "dev": true, "requires": { "node-gyp-build": "^4.2.0" + }, + "dependencies": { + "node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "dev": true + } } }, "utf8": { @@ -14723,7 +14743,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -15087,7 +15106,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -15113,8 +15131,7 @@ "has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" }, "has-to-string-tag-x": { "version": "1.4.1", diff --git a/package.json b/package.json index dce53f5d..cfb6ee28 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "dev:deployUIProvider": "hardhat --network kovan deploy-UiPoolDataProvider", "main:deployUIProvider": "hardhat --network main deploy-UiPoolDataProvider", "matic:deployUIProvider": "hardhat --network matic deploy-UiPoolDataProvider", + "mumbai:deployUIProvider": "hardhat --network mumbai deploy-UiPoolDataProvider", "dev:deployUniswapRepayAdapter": "hardhat --network kovan deploy-UniswapRepayAdapter --provider 0x88757f2f99175387aB4C6a4b3067c77A695b0349 --router 0xfcd87315f0e4067070ade8682fcdbc3006631441 --weth 0xd0a1e359811322d97991e03f863a0c30c2cf029c", "dev:UniswapLiquiditySwapAdapter": "hardhat --network kovan deploy-UniswapLiquiditySwapAdapter --provider 0x88757f2f99175387aB4C6a4b3067c77A695b0349 --router 0xfcd87315f0e4067070ade8682fcdbc3006631441 --weth 0xd0a1e359811322d97991e03f863a0c30c2cf029c", "main:deployUniswapRepayAdapter": "hardhat --network main deploy-UniswapRepayAdapter --provider 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 --router 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D --weth 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", diff --git a/tasks/deployments/deploy-UiPoolDataProvider.ts b/tasks/deployments/deploy-UiPoolDataProvider.ts index 64a6dae4..79d75a49 100644 --- a/tasks/deployments/deploy-UiPoolDataProvider.ts +++ b/tasks/deployments/deploy-UiPoolDataProvider.ts @@ -6,7 +6,7 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider .addFlag('verify', 'Verify UiPoolDataProvider contract via Etherscan API.') .setAction(async ({ verify }, localBRE) => { await localBRE.run('set-DRE'); - + console.log('founds: ', await localBRE.ethers.getSigners()); if (!localBRE.network.config.chainId) { throw new Error('INVALID_CHAIN_ID'); } @@ -24,6 +24,10 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider incentivesController: '0x357D51124f59836DeD84c8a1730D72B749d8BC23', aaveOracle: '0x21451bD7b528896B4AB2b9764b521D6ed641708d', }, + [ePolygonNetwork.mumbai]: { + incentivesController: '0xc31c45a46e55f714f9CB2b43Ae688487C16616e2', + aaveOracle: '0x584c84AA7aE807e18957f8E3693BccBD482357E2', + }, }; console.log(`\n- UiPoolDataProvider deployment`); From f7fde949a75bb0e890d67d9619883c74e4decd3a Mon Sep 17 00:00:00 2001 From: sendra Date: Fri, 9 Apr 2021 15:06:57 +0200 Subject: [PATCH 193/219] updated with latest addresses --- tasks/deployments/deploy-UiPoolDataProvider.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tasks/deployments/deploy-UiPoolDataProvider.ts b/tasks/deployments/deploy-UiPoolDataProvider.ts index 79d75a49..21bf08ed 100644 --- a/tasks/deployments/deploy-UiPoolDataProvider.ts +++ b/tasks/deployments/deploy-UiPoolDataProvider.ts @@ -6,7 +6,6 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider .addFlag('verify', 'Verify UiPoolDataProvider contract via Etherscan API.') .setAction(async ({ verify }, localBRE) => { await localBRE.run('set-DRE'); - console.log('founds: ', await localBRE.ethers.getSigners()); if (!localBRE.network.config.chainId) { throw new Error('INVALID_CHAIN_ID'); } @@ -25,8 +24,8 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider aaveOracle: '0x21451bD7b528896B4AB2b9764b521D6ed641708d', }, [ePolygonNetwork.mumbai]: { - incentivesController: '0xc31c45a46e55f714f9CB2b43Ae688487C16616e2', - aaveOracle: '0x584c84AA7aE807e18957f8E3693BccBD482357E2', + incentivesController: '0xa20493558dB697369ffB1b4A4Dc6455ee26aEeff', + aaveOracle: '0xE6d947B89c837B761bf3B7D48bB406a7a2EEc3e0', }, }; From 1849484cbf8c040c09f8faa6edaae06db6c980e0 Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 12 Apr 2021 09:37:55 +0200 Subject: [PATCH 194/219] updated with new mumbai addresses --- tasks/deployments/deploy-UiPoolDataProvider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/deployments/deploy-UiPoolDataProvider.ts b/tasks/deployments/deploy-UiPoolDataProvider.ts index 21bf08ed..881e71eb 100644 --- a/tasks/deployments/deploy-UiPoolDataProvider.ts +++ b/tasks/deployments/deploy-UiPoolDataProvider.ts @@ -24,8 +24,8 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider aaveOracle: '0x21451bD7b528896B4AB2b9764b521D6ed641708d', }, [ePolygonNetwork.mumbai]: { - incentivesController: '0xa20493558dB697369ffB1b4A4Dc6455ee26aEeff', - aaveOracle: '0xE6d947B89c837B761bf3B7D48bB406a7a2EEc3e0', + incentivesController: '0xCA8f76C244271A857CE76263e60d294EB24186A8', + aaveOracle: '0x3cC6db8dBBa233Fe342c2c8379993aCa231674bd', }, }; From 47b3d8ff65c2280a183edee8b626123152090676 Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 12 Apr 2021 10:56:33 +0200 Subject: [PATCH 195/219] new mumbai addresses --- tasks/deployments/deploy-UiPoolDataProvider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/deployments/deploy-UiPoolDataProvider.ts b/tasks/deployments/deploy-UiPoolDataProvider.ts index 881e71eb..31290c2d 100644 --- a/tasks/deployments/deploy-UiPoolDataProvider.ts +++ b/tasks/deployments/deploy-UiPoolDataProvider.ts @@ -24,8 +24,8 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider aaveOracle: '0x21451bD7b528896B4AB2b9764b521D6ed641708d', }, [ePolygonNetwork.mumbai]: { - incentivesController: '0xCA8f76C244271A857CE76263e60d294EB24186A8', - aaveOracle: '0x3cC6db8dBBa233Fe342c2c8379993aCa231674bd', + incentivesController: '0xd3aC1EBa90c21D70464dDafd30E3Ff8941002929', + aaveOracle: '0x48beE000e8f86d0ED8c0fB22D63e789b0cE9Aed1', }, }; From 94790ecc46ccab0ef03626a744afb53f0258d308 Mon Sep 17 00:00:00 2001 From: The3D Date: Mon, 12 Apr 2021 11:10:22 +0200 Subject: [PATCH 196/219] Fixed interface update --- contracts/protocol/tokenization/AToken.sol | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/protocol/tokenization/AToken.sol b/contracts/protocol/tokenization/AToken.sol index f2784732..46aae19f 100644 --- a/contracts/protocol/tokenization/AToken.sol +++ b/contracts/protocol/tokenization/AToken.sol @@ -273,7 +273,7 @@ contract AToken is /** * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) **/ - function UNDERLYING_ASSET_ADDRESS() public view returns (address) { + function UNDERLYING_ASSET_ADDRESS() public override view returns (address) { return _underlyingAsset; } diff --git a/package.json b/package.json index 7076c576..b47534a9 100644 --- a/package.json +++ b/package.json @@ -153,4 +153,4 @@ "ethereum", "solidity" ] -} \ No newline at end of file +} From b0caaee52e7483ca50809a29765afcd84ae6e928 Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 12 Apr 2021 21:36:34 +0200 Subject: [PATCH 197/219] updated for latest mumbai addresses --- tasks/deployments/deploy-UiPoolDataProvider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/deployments/deploy-UiPoolDataProvider.ts b/tasks/deployments/deploy-UiPoolDataProvider.ts index 31290c2d..c2646923 100644 --- a/tasks/deployments/deploy-UiPoolDataProvider.ts +++ b/tasks/deployments/deploy-UiPoolDataProvider.ts @@ -24,8 +24,8 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider aaveOracle: '0x21451bD7b528896B4AB2b9764b521D6ed641708d', }, [ePolygonNetwork.mumbai]: { - incentivesController: '0xd3aC1EBa90c21D70464dDafd30E3Ff8941002929', - aaveOracle: '0x48beE000e8f86d0ED8c0fB22D63e789b0cE9Aed1', + incentivesController: '0xd41aE58e803Edf4304334acCE4DC4Ec34a63C644', + aaveOracle: '0xC365C653f7229894F93994CD0b30947Ab69Ff1D5', }, }; From 5f817c7c09139585c7dbc18aef07380ab8148869 Mon Sep 17 00:00:00 2001 From: Zer0dot Date: Mon, 19 Apr 2021 11:04:04 -0400 Subject: [PATCH 198/219] fix: removed unused hardhat console import --- .../protocol/lendingpool/DefaultReserveInterestRateStrategy.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol b/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol index af4db241..7b321d0c 100644 --- a/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol +++ b/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol @@ -8,7 +8,6 @@ import {PercentageMath} from '../libraries/math/PercentageMath.sol'; import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; import {ILendingRateOracle} from '../../interfaces/ILendingRateOracle.sol'; import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol'; -import 'hardhat/console.sol'; /** * @title DefaultReserveInterestRateStrategy contract From 21fc210901c7d50fbd1acfe1a6b8cc97b59ed3c3 Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 19 Apr 2021 17:17:30 +0200 Subject: [PATCH 199/219] fix: updated interface to last version --- .../interfaces/IAaveIncentivesController.sol | 103 +++++++++++++++++- 1 file changed, 99 insertions(+), 4 deletions(-) diff --git a/contracts/interfaces/IAaveIncentivesController.sol b/contracts/interfaces/IAaveIncentivesController.sol index 8e9c74a7..4b49eb23 100644 --- a/contracts/interfaces/IAaveIncentivesController.sol +++ b/contracts/interfaces/IAaveIncentivesController.sol @@ -9,24 +9,119 @@ interface IAaveIncentivesController { uint256 index; } - function REWARD_TOKEN() external view returns (address rewardToken); + event RewardsAccrued(address indexed user, uint256 amount); - function PRECISION() external view returns (uint8); + event RewardsClaimed( + address indexed user, + address indexed to, + uint256 amount + ); + + event RewardsClaimed( + address indexed user, + address indexed to, + address indexed claimer, + uint256 amount + ); + + event ClaimerSet(address indexed user, address indexed claimer); function assets(address underlying) external view returns (AssetData memory assets); + /** + * @dev Whitelists an address to claim the rewards on behalf of another address + * @param user The address of the user + * @param claimer The address of the claimer + */ + function setClaimer(address user, address claimer) external; + + /** + * @dev Returns the whitelisted claimer for a certain address (0x0 if not set) + * @param user The address of the user + * @return The claimer address + */ + function getClaimer(address user) external view returns (address); + + /** + * @dev Configure assets for a certain rewards emission + * @param assets The assets to incentivize + * @param emissionsPerSecond The emission for each asset + */ + function configureAssets(address[] calldata assets, uint256[] calldata emissionsPerSecond) + external; + + + /** + * @dev Called by the corresponding asset on any update that affects the rewards distribution + * @param asset The address of the user + * @param userBalance The balance of the user of the asset in the lending pool + * @param totalSupply The total supply of the asset in the lending pool + **/ function handleAction( - address user, + address asset, uint256 userBalance, uint256 totalSupply ) external; + /** + * @dev Returns the total of rewards of an user, already accrued + not yet accrued + * @param user The address of the user + * @return The rewards + **/ function getRewardsBalance(address[] calldata assets, address user) external view returns (uint256); - function getUserUnclaimedRewards(address _user) external view returns (uint256); + /** + * @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards + * @param amount Amount of rewards to claim + * @param to Address that will be receiving the rewards + * @return Rewards claimed + **/ + function claimRewards( + address[] calldata assets, + uint256 amount, + address to + ) external returns (uint256); + /** + * @dev Claims reward for an user on behalf, on all the assets of the lending pool, accumulating the pending rewards. The caller must + * be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager + * @param amount Amount of rewards to claim + * @param user Address to check and claim rewards + * @param to Address that will be receiving the rewards + * @return Rewards claimed + **/ + function claimRewardsOnBehalf( + address[] calldata assets, + uint256 amount, + address user, + address to + ) external returns (uint256); + + /** + * @dev returns the unclaimed rewards of the user + * @param user the address of the user + * @return the unclaimed user rewards + */ + function getUserUnclaimedRewards(address user) external view returns (uint256); + + /** + * @dev returns the unclaimed rewards of the user + * @param user the address of the user + * @param asset The asset to incentivize + * @return the user index for the asset + */ function getUserAssetData(address user, address asset) external view returns (uint256); + + /** + * @dev for backward compatibility with previous implementation of the Incentives controller + */ + function REWARD_TOKEN() external view returns (address); + + /** + * @dev for backward compatibility with previous implementation of the Incentives controller + */ + function PRECISION() external view returns (uint8); } From 360d37f9f87bcb7198202fb2d50ab49376f87d7a Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 19 Apr 2021 17:23:45 +0200 Subject: [PATCH 200/219] fix: updated mainnet task to deploy ui helper --- package.json | 4 ++-- tasks/deployments/deploy-UiPoolDataProvider.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index cfb6ee28..c3a97f23 100644 --- a/package.json +++ b/package.json @@ -61,8 +61,8 @@ "print-contracts:kovan": "npm run hardhat:kovan -- print-contracts", "print-contracts:main": "npm run hardhat:main -- print-contracts", "print-contracts:ropsten": "npm run hardhat:main -- print-contracts", - "dev:deployUIProvider": "hardhat --network kovan deploy-UiPoolDataProvider", - "main:deployUIProvider": "hardhat --network main deploy-UiPoolDataProvider", + "dev:deployUIProvider": "hardhat --network kovan deploy-UiPoolDataProvider --verify", + "main:deployUIProvider": "hardhat --network main deploy-UiPoolDataProvider --verify", "matic:deployUIProvider": "hardhat --network matic deploy-UiPoolDataProvider", "mumbai:deployUIProvider": "hardhat --network mumbai deploy-UiPoolDataProvider", "dev:deployUniswapRepayAdapter": "hardhat --network kovan deploy-UniswapRepayAdapter --provider 0x88757f2f99175387aB4C6a4b3067c77A695b0349 --router 0xfcd87315f0e4067070ade8682fcdbc3006631441 --weth 0xd0a1e359811322d97991e03f863a0c30c2cf029c", diff --git a/tasks/deployments/deploy-UiPoolDataProvider.ts b/tasks/deployments/deploy-UiPoolDataProvider.ts index c2646923..1158fe90 100644 --- a/tasks/deployments/deploy-UiPoolDataProvider.ts +++ b/tasks/deployments/deploy-UiPoolDataProvider.ts @@ -15,10 +15,10 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider // incentivesController: '', // aaveOracle: '', // }, - // [eEthereumNetwork.main]: { - // incentivesController: '', - // aaveOracle: '0xa50ba011c48153de246e5192c8f9258a2ba79ca9', - // }, + [eEthereumNetwork.main]: { + incentivesController: '0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5', + aaveOracle: '0xa50ba011c48153de246e5192c8f9258a2ba79ca9', + }, [ePolygonNetwork.matic]: { incentivesController: '0x357D51124f59836DeD84c8a1730D72B749d8BC23', aaveOracle: '0x21451bD7b528896B4AB2b9764b521D6ed641708d', From 16a9292c2763de6abb99a0a9f6becd84af348573 Mon Sep 17 00:00:00 2001 From: eboado Date: Tue, 20 Apr 2021 19:04:40 +0200 Subject: [PATCH 201/219] - Fix typo on whitepaper --- aave-v2-whitepaper.pdf | Bin 868481 -> 868480 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/aave-v2-whitepaper.pdf b/aave-v2-whitepaper.pdf index 47d31445f20d413afa97b67b702c5d32aa340dd9..57b60473665811b076e8a6839b5773950780fe29 100644 GIT binary patch delta 4311 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 Date: Wed, 21 Apr 2021 17:45:19 +0200 Subject: [PATCH 202/219] Updated to new asset struct interface --- contracts/interfaces/IAaveIncentivesController.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/interfaces/IAaveIncentivesController.sol b/contracts/interfaces/IAaveIncentivesController.sol index 4b49eb23..55f0db7d 100644 --- a/contracts/interfaces/IAaveIncentivesController.sol +++ b/contracts/interfaces/IAaveIncentivesController.sol @@ -4,9 +4,9 @@ pragma experimental ABIEncoderV2; interface IAaveIncentivesController { struct AssetData { - uint128 emissionPerSecond; - uint128 lastUpdateTimestamp; - uint256 index; + uint104 emissionPerSecond; + uint104 index; + uint40 lastUpdateTimestamp; } event RewardsAccrued(address indexed user, uint256 amount); From 2a19131b7af38bf5233e0d34f83b450635e03676 Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 21 Apr 2021 18:00:00 +0200 Subject: [PATCH 203/219] feat: Updated to new interface of Incentives Controller --- .../interfaces/IAaveIncentivesController.sol | 35 ++++++++++--------- contracts/misc/UiPoolDataProvider.sol | 28 ++++++++------- .../misc/interfaces/IUiPoolDataProvider.sol | 6 ++-- 3 files changed, 36 insertions(+), 33 deletions(-) diff --git a/contracts/interfaces/IAaveIncentivesController.sol b/contracts/interfaces/IAaveIncentivesController.sol index 55f0db7d..efa132b2 100644 --- a/contracts/interfaces/IAaveIncentivesController.sol +++ b/contracts/interfaces/IAaveIncentivesController.sol @@ -3,19 +3,9 @@ pragma solidity 0.6.12; pragma experimental ABIEncoderV2; interface IAaveIncentivesController { - struct AssetData { - uint104 emissionPerSecond; - uint104 index; - uint40 lastUpdateTimestamp; - } - event RewardsAccrued(address indexed user, uint256 amount); - event RewardsClaimed( - address indexed user, - address indexed to, - uint256 amount - ); + event RewardsClaimed(address indexed user, address indexed to, uint256 amount); event RewardsClaimed( address indexed user, @@ -26,7 +16,19 @@ interface IAaveIncentivesController { event ClaimerSet(address indexed user, address indexed claimer); - function assets(address underlying) external view returns (AssetData memory assets); + /* + * @dev Returns the configuration of the distribution for a certain asset + * @param asset The address of the reference asset of the distribution + * @return The asset index, the emission per second and the last updated timestamp + **/ + function getAssetData(address asset) + external + view + returns ( + uint256, + uint256, + uint256 + ); /** * @dev Whitelists an address to claim the rewards on behalf of another address @@ -50,7 +52,6 @@ interface IAaveIncentivesController { function configureAssets(address[] calldata assets, uint256[] calldata emissionsPerSecond) external; - /** * @dev Called by the corresponding asset on any update that affects the rewards distribution * @param asset The address of the user @@ -116,12 +117,12 @@ interface IAaveIncentivesController { function getUserAssetData(address user, address asset) external view returns (uint256); /** - * @dev for backward compatibility with previous implementation of the Incentives controller - */ + * @dev for backward compatibility with previous implementation of the Incentives controller + */ function REWARD_TOKEN() external view returns (address); /** - * @dev for backward compatibility with previous implementation of the Incentives controller - */ + * @dev for backward compatibility with previous implementation of the Incentives controller + */ function PRECISION() external view returns (uint8); } diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 7d2aef55..a3f25c05 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -131,21 +131,23 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ); // incentives - IAaveIncentivesController.AssetData memory tokenIncentivesInfo = - incentivesController.assets(reserveData.aTokenAddress); - reserveData.aEmissionPerSecond = tokenIncentivesInfo.emissionPerSecond; - reserveData.aIncentivesLastUpdateTimestamp = tokenIncentivesInfo.lastUpdateTimestamp; - reserveData.aTokenIncentivesIndex = tokenIncentivesInfo.index; + ( + reserveData.aEmissionPerSecond, + reserveData.aIncentivesLastUpdateTimestamp, + reserveData.aTokenIncentivesIndex + ) = incentivesController.getAssetData(reserveData.aTokenAddress); - tokenIncentivesInfo = incentivesController.assets(reserveData.stableDebtTokenAddress); - reserveData.sEmissionPerSecond = tokenIncentivesInfo.emissionPerSecond; - reserveData.sIncentivesLastUpdateTimestamp = tokenIncentivesInfo.lastUpdateTimestamp; - reserveData.sTokenIncentivesIndex = tokenIncentivesInfo.index; + ( + reserveData.sEmissionPerSecond, + reserveData.sIncentivesLastUpdateTimestamp, + reserveData.sTokenIncentivesIndex + ) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress); - tokenIncentivesInfo = incentivesController.assets(reserveData.variableDebtTokenAddress); - reserveData.vEmissionPerSecond = tokenIncentivesInfo.emissionPerSecond; - reserveData.vIncentivesLastUpdateTimestamp = tokenIncentivesInfo.lastUpdateTimestamp; - reserveData.vTokenIncentivesIndex = tokenIncentivesInfo.index; + ( + reserveData.vEmissionPerSecond, + reserveData.vIncentivesLastUpdateTimestamp, + reserveData.vTokenIncentivesIndex + ) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress); if (user != address(0)) { // incentives diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index 43e4e997..34f06d1c 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -43,9 +43,9 @@ interface IUiPoolDataProvider { uint256 stableRateSlope1; uint256 stableRateSlope2; // incentives - uint128 aEmissionPerSecond; - uint128 vEmissionPerSecond; - uint128 sEmissionPerSecond; + uint256 aEmissionPerSecond; + uint256 vEmissionPerSecond; + uint256 sEmissionPerSecond; uint256 aIncentivesLastUpdateTimestamp; uint256 vIncentivesLastUpdateTimestamp; uint256 sIncentivesLastUpdateTimestamp; From 9df1502f2262d0783cf2c8c0001066fe8b82f0af Mon Sep 17 00:00:00 2001 From: sendra Date: Wed, 21 Apr 2021 19:16:11 +0200 Subject: [PATCH 204/219] correct mainnet incentives controller --- tasks/deployments/deploy-UiPoolDataProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/deployments/deploy-UiPoolDataProvider.ts b/tasks/deployments/deploy-UiPoolDataProvider.ts index 1158fe90..984d5a13 100644 --- a/tasks/deployments/deploy-UiPoolDataProvider.ts +++ b/tasks/deployments/deploy-UiPoolDataProvider.ts @@ -16,7 +16,7 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider // aaveOracle: '', // }, [eEthereumNetwork.main]: { - incentivesController: '0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5', + incentivesController: '0xd784927Ff2f95ba542BfC824c8a8a98F3495f6b5', aaveOracle: '0xa50ba011c48153de246e5192c8f9258a2ba79ca9', }, [ePolygonNetwork.matic]: { From 7ffb0e573fbf48160d93b974bd530ff06d3aea0d Mon Sep 17 00:00:00 2001 From: David Racero Date: Thu, 22 Apr 2021 10:17:45 +0200 Subject: [PATCH 205/219] fix: Change the order of return variables of incentives getAssetData --- contracts/misc/UiPoolDataProvider.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index a3f25c05..bbd78f29 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -132,21 +132,21 @@ contract UiPoolDataProvider is IUiPoolDataProvider { // incentives ( + reserveData.aTokenIncentivesIndex, reserveData.aEmissionPerSecond, - reserveData.aIncentivesLastUpdateTimestamp, - reserveData.aTokenIncentivesIndex + reserveData.aIncentivesLastUpdateTimestamp ) = incentivesController.getAssetData(reserveData.aTokenAddress); ( + reserveData.sTokenIncentivesIndex, reserveData.sEmissionPerSecond, - reserveData.sIncentivesLastUpdateTimestamp, - reserveData.sTokenIncentivesIndex + reserveData.sIncentivesLastUpdateTimestamp ) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress); ( + reserveData.vTokenIncentivesIndex, reserveData.vEmissionPerSecond, - reserveData.vIncentivesLastUpdateTimestamp, - reserveData.vTokenIncentivesIndex + reserveData.vIncentivesLastUpdateTimestamp ) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress); if (user != address(0)) { From 3a10205aefe6af387adcdf069531a1c215848f99 Mon Sep 17 00:00:00 2001 From: The3D Date: Fri, 23 Apr 2021 16:03:24 +0200 Subject: [PATCH 206/219] config: updated the reference fork to berlin --- hardhat.config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 234be8f2..713a6733 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -99,7 +99,7 @@ const buidlerConfig: HardhatUserConfig = { mumbai: getCommonNetworkConfig(ePolygonNetwork.mumbai, 80001), xdai: getCommonNetworkConfig(eXDaiNetwork.xdai, 100), hardhat: { - hardfork: 'istanbul', + hardfork: 'berlin', blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, gas: DEFAULT_BLOCK_GAS_LIMIT, gasPrice: 8000000000, @@ -113,7 +113,7 @@ const buidlerConfig: HardhatUserConfig = { forking: mainnetFork, }, buidlerevm_docker: { - hardfork: 'istanbul', + hardfork: 'berlin', blockGasLimit: 9500000, gas: 9500000, gasPrice: 8000000000, From c46b3932f3baca964f64028550ceb4e64e533105 Mon Sep 17 00:00:00 2001 From: The3D Date: Fri, 23 Apr 2021 16:07:14 +0200 Subject: [PATCH 207/219] config: updated package.json --- package-lock.json | 1122 ++++++++++++++++++++++++++++++++++++++++++++- package.json | 2 +- 2 files changed, 1104 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index b05b76cb..d562af03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -311,6 +311,824 @@ "postinstall-postinstall": "^2.1.0" } }, + "@ethereumjs/block": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@ethereumjs/block/-/block-3.2.1.tgz", + "integrity": "sha512-FCxo5KwwULne2A2Yuae4iaGGqSsRjwzXOlDhGalOFiBbLfP3hE04RHaHGw4c8vh1PfOrLauwi0dQNUBkOG3zIA==", + "dev": true, + "requires": { + "@ethereumjs/common": "^2.2.0", + "@ethereumjs/tx": "^3.1.3", + "ethereumjs-util": "^7.0.10", + "merkle-patricia-tree": "^4.1.0" + }, + "dependencies": { + "@types/bn.js": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", + "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "abstract-leveldown": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz", + "integrity": "sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "deferred-leveldown": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz", + "integrity": "sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==", + "dev": true, + "requires": { + "abstract-leveldown": "~6.2.1", + "inherits": "^2.0.3" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + } + } + }, + "encoding-down": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-6.3.0.tgz", + "integrity": "sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==", + "dev": true, + "requires": { + "abstract-leveldown": "^6.2.1", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0" + } + }, + "ethereumjs-util": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz", + "integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==", + "dev": true, + "requires": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.4" + } + }, + "level-codec": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", + "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", + "dev": true, + "requires": { + "buffer": "^5.6.0" + } + }, + "level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "dev": true, + "requires": { + "errno": "~0.1.1" + } + }, + "level-iterator-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz", + "integrity": "sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.4.0", + "xtend": "^4.0.2" + } + }, + "level-mem": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-5.0.1.tgz", + "integrity": "sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg==", + "dev": true, + "requires": { + "level-packager": "^5.0.3", + "memdown": "^5.0.0" + } + }, + "level-packager": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-5.1.1.tgz", + "integrity": "sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ==", + "dev": true, + "requires": { + "encoding-down": "^6.3.0", + "levelup": "^4.3.2" + } + }, + "level-ws": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-2.0.0.tgz", + "integrity": "sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^3.1.0", + "xtend": "^4.0.1" + } + }, + "levelup": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-4.4.0.tgz", + "integrity": "sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==", + "dev": true, + "requires": { + "deferred-leveldown": "~5.3.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~4.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "memdown": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-5.1.0.tgz", + "integrity": "sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw==", + "dev": true, + "requires": { + "abstract-leveldown": "~6.2.1", + "functional-red-black-tree": "~1.0.1", + "immediate": "~3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", + "dev": true + } + } + }, + "merkle-patricia-tree": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-4.1.0.tgz", + "integrity": "sha512-vmP1J7FwIpprFMVjjSMM1JAwFce85Q+tp0TYIedYv8qaMh2oLUZ3ETXn9wbgi9S6elySzKzGa+Ai6VNKGEwSlg==", + "dev": true, + "requires": { + "@types/levelup": "^4.3.0", + "ethereumjs-util": "^7.0.8", + "level-mem": "^5.0.1", + "level-ws": "^2.0.0", + "readable-stream": "^3.6.0", + "rlp": "^2.2.3", + "semaphore-async-await": "^1.5.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "@ethereumjs/blockchain": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@ethereumjs/blockchain/-/blockchain-5.2.1.tgz", + "integrity": "sha512-+hshP2qSOOFsiYvZCbaDQFG7jYTWafE8sfBi+pAsdhAHfP7BN7VLyob7qoQISgwS1s7NTR4c4+2t/woU9ahItw==", + "dev": true, + "requires": { + "@ethereumjs/block": "^3.2.0", + "@ethereumjs/common": "^2.2.0", + "@ethereumjs/ethash": "^1.0.0", + "debug": "^2.2.0", + "ethereumjs-util": "^7.0.9", + "level-mem": "^5.0.1", + "lru-cache": "^5.1.1", + "rlp": "^2.2.4", + "semaphore-async-await": "^1.5.1" + }, + "dependencies": { + "@types/bn.js": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", + "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "abstract-leveldown": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz", + "integrity": "sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deferred-leveldown": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz", + "integrity": "sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==", + "dev": true, + "requires": { + "abstract-leveldown": "~6.2.1", + "inherits": "^2.0.3" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + } + } + }, + "encoding-down": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-6.3.0.tgz", + "integrity": "sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==", + "dev": true, + "requires": { + "abstract-leveldown": "^6.2.1", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0" + } + }, + "ethereumjs-util": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz", + "integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==", + "dev": true, + "requires": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.4" + } + }, + "level-codec": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", + "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", + "dev": true, + "requires": { + "buffer": "^5.6.0" + } + }, + "level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "dev": true, + "requires": { + "errno": "~0.1.1" + } + }, + "level-iterator-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz", + "integrity": "sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.4.0", + "xtend": "^4.0.2" + } + }, + "level-mem": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-5.0.1.tgz", + "integrity": "sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg==", + "dev": true, + "requires": { + "level-packager": "^5.0.3", + "memdown": "^5.0.0" + } + }, + "level-packager": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-5.1.1.tgz", + "integrity": "sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ==", + "dev": true, + "requires": { + "encoding-down": "^6.3.0", + "levelup": "^4.3.2" + } + }, + "levelup": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-4.4.0.tgz", + "integrity": "sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==", + "dev": true, + "requires": { + "deferred-leveldown": "~5.3.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~4.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "memdown": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-5.1.0.tgz", + "integrity": "sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw==", + "dev": true, + "requires": { + "abstract-leveldown": "~6.2.1", + "functional-red-black-tree": "~1.0.1", + "immediate": "~3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "@ethereumjs/common": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.2.0.tgz", + "integrity": "sha512-PyQiTG00MJtBRkJmv46ChZL8u2XWxNBeAthznAUIUiefxPAXjbkuiCZOuncgJS34/XkMbNc9zMt/PlgKRBElig==", + "dev": true, + "requires": { + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.0.9" + }, + "dependencies": { + "@types/bn.js": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", + "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "ethereumjs-util": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz", + "integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==", + "dev": true, + "requires": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.4" + } + } + } + }, + "@ethereumjs/ethash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/ethash/-/ethash-1.0.0.tgz", + "integrity": "sha512-iIqnGG6NMKesyOxv2YctB2guOVX18qMAWlj3QlZyrc+GqfzLqoihti+cVNQnyNxr7eYuPdqwLQOFuPe6g/uKjw==", + "dev": true, + "requires": { + "@types/levelup": "^4.3.0", + "buffer-xor": "^2.0.1", + "ethereumjs-util": "^7.0.7", + "miller-rabin": "^4.0.0" + }, + "dependencies": { + "@types/bn.js": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", + "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "buffer-xor": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", + "integrity": "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "ethereumjs-util": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz", + "integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==", + "dev": true, + "requires": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.4" + } + } + } + }, + "@ethereumjs/tx": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.1.4.tgz", + "integrity": "sha512-6cJpmmjCpG5ZVN9NJYtWvmrEQcevw9DIR8hj2ca2PszD2fxbIFXky3Z37gpf8S6u0Npv09kG8It+G4xjydZVLg==", + "dev": true, + "requires": { + "@ethereumjs/common": "^2.2.0", + "ethereumjs-util": "^7.0.10" + }, + "dependencies": { + "@types/bn.js": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", + "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "ethereumjs-util": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz", + "integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==", + "dev": true, + "requires": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.4" + } + } + } + }, + "@ethereumjs/vm": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/vm/-/vm-5.3.2.tgz", + "integrity": "sha512-QmCUQrW6xbhgEbQh9njue4kAJdM056C+ytBFUTF/kDYa3kNDm4Qxp9HUyTlt1OCSXvDhws0qqlh8+q+pmXpN7g==", + "dev": true, + "requires": { + "@ethereumjs/block": "^3.2.1", + "@ethereumjs/blockchain": "^5.2.1", + "@ethereumjs/common": "^2.2.0", + "@ethereumjs/tx": "^3.1.3", + "async-eventemitter": "^0.2.4", + "core-js-pure": "^3.0.1", + "debug": "^2.2.0", + "ethereumjs-util": "^7.0.10", + "functional-red-black-tree": "^1.0.1", + "mcl-wasm": "^0.7.1", + "merkle-patricia-tree": "^4.1.0", + "rustbn.js": "~0.2.0", + "util.promisify": "^1.0.1" + }, + "dependencies": { + "@types/bn.js": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", + "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "abstract-leveldown": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz", + "integrity": "sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deferred-leveldown": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz", + "integrity": "sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==", + "dev": true, + "requires": { + "abstract-leveldown": "~6.2.1", + "inherits": "^2.0.3" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + } + } + }, + "encoding-down": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-6.3.0.tgz", + "integrity": "sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==", + "dev": true, + "requires": { + "abstract-leveldown": "^6.2.1", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0" + } + }, + "ethereumjs-util": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz", + "integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==", + "dev": true, + "requires": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.4" + } + }, + "level-codec": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", + "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", + "dev": true, + "requires": { + "buffer": "^5.6.0" + } + }, + "level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "dev": true, + "requires": { + "errno": "~0.1.1" + } + }, + "level-iterator-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz", + "integrity": "sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.4.0", + "xtend": "^4.0.2" + } + }, + "level-mem": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-5.0.1.tgz", + "integrity": "sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg==", + "dev": true, + "requires": { + "level-packager": "^5.0.3", + "memdown": "^5.0.0" + } + }, + "level-packager": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-5.1.1.tgz", + "integrity": "sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ==", + "dev": true, + "requires": { + "encoding-down": "^6.3.0", + "levelup": "^4.3.2" + } + }, + "level-ws": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-2.0.0.tgz", + "integrity": "sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^3.1.0", + "xtend": "^4.0.1" + } + }, + "levelup": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-4.4.0.tgz", + "integrity": "sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==", + "dev": true, + "requires": { + "deferred-leveldown": "~5.3.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~4.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "memdown": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-5.1.0.tgz", + "integrity": "sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw==", + "dev": true, + "requires": { + "abstract-leveldown": "~6.2.1", + "functional-red-black-tree": "~1.0.1", + "immediate": "~3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", + "dev": true + } + } + }, + "merkle-patricia-tree": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-4.1.0.tgz", + "integrity": "sha512-vmP1J7FwIpprFMVjjSMM1JAwFce85Q+tp0TYIedYv8qaMh2oLUZ3ETXn9wbgi9S6elySzKzGa+Ai6VNKGEwSlg==", + "dev": true, + "requires": { + "@types/levelup": "^4.3.0", + "ethereumjs-util": "^7.0.8", + "level-mem": "^5.0.1", + "level-ws": "^2.0.0", + "readable-stream": "^3.6.0", + "rlp": "^2.2.3", + "semaphore-async-await": "^1.5.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, "@ethersproject/abi": { "version": "5.0.13", "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.13.tgz", @@ -1810,6 +2628,12 @@ "integrity": "sha512-MM8PmsblePaxy5BCYEuPtR4ajigPf504VRQzZgFYqs6KuFnJxbOjF8jNYT12P6UvUX7us75Wc78QdbvOHbb4hA==", "dev": true }, + "@types/abstract-leveldown": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/abstract-leveldown/-/abstract-leveldown-5.0.1.tgz", + "integrity": "sha512-wYxU3kp5zItbxKmeRYCEplS2MW7DzyBnxPGj+GJVHZEUZiK/nn5Ei1sUFgURDh+X051+zsGe28iud3oHjrYWQQ==", + "dev": true + }, "@types/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", @@ -1853,6 +2677,16 @@ "@types/node": "*" } }, + "@types/levelup": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/levelup/-/levelup-4.3.1.tgz", + "integrity": "sha512-n//PeTpbHLjMLTIgW5B/g06W/6iuTBHuvUka2nFL9APMSVMNe2r4enADfu3CIE9IyV9E+uquf9OEQQqrDeg24A==", + "dev": true, + "requires": { + "@types/abstract-leveldown": "*", + "@types/node": "*" + } + }, "@types/lodash": { "version": "4.14.168", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz", @@ -3238,6 +4072,16 @@ } } }, + "crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "dev": true, + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, "create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -4687,6 +5531,12 @@ } } }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "dev": true + }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -14912,15 +15762,19 @@ } }, "hardhat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.1.1.tgz", - "integrity": "sha512-55XMqB5QoeRg3m56rBg0NQgU//GPqOC9t4RbRSU3pdBJGHGXFTUh8fjTPxnWJNu9r72Zju++syGcCkPGwftyvw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.2.1.tgz", + "integrity": "sha512-8s7MtGXdh0NDwQKdlA8m8QdloVIN1+hv5aFpn0G5Ljj9vfNY9kUoc0a9pMboeGbd9WrS+XrZs5YlsPgQjaW/Tg==", "dev": true, "requires": { - "@nomiclabs/ethereumjs-vm": "4.2.2", + "@ethereumjs/block": "^3.2.1", + "@ethereumjs/blockchain": "^5.2.1", + "@ethereumjs/common": "^2.2.0", + "@ethereumjs/tx": "^3.1.3", + "@ethereumjs/vm": "^5.3.2", "@sentry/node": "^5.18.1", "@solidity-parser/parser": "^0.11.0", - "@types/bn.js": "^4.11.5", + "@types/bn.js": "^5.1.0", "@types/lru-cache": "^5.1.0", "abort-controller": "^3.0.0", "adm-zip": "^0.4.16", @@ -14934,11 +15788,7 @@ "eth-sig-util": "^2.5.2", "ethereum-cryptography": "^0.1.2", "ethereumjs-abi": "^0.6.8", - "ethereumjs-account": "^3.0.0", - "ethereumjs-block": "^2.2.2", - "ethereumjs-common": "^1.5.0", - "ethereumjs-tx": "^2.1.2", - "ethereumjs-util": "^6.2.0", + "ethereumjs-util": "^7.0.10", "find-up": "^2.1.0", "fp-ts": "1.19.3", "fs-extra": "^7.0.1", @@ -14946,7 +15796,7 @@ "immutable": "^4.0.0-rc.12", "io-ts": "1.10.4", "lodash": "^4.17.11", - "merkle-patricia-tree": "3.0.0", + "merkle-patricia-tree": "^4.1.0", "mnemonist": "^0.38.0", "mocha": "^7.1.2", "node-fetch": "^2.6.0", @@ -14970,25 +15820,89 @@ "integrity": "sha512-H8BSBoKE8EubJa0ONqecA2TviT3TnHeC4NpgnAHSUiuhZoQBfPB4L2P9bs8R6AoTW10Endvh3vc+fomVMIDIYQ==", "dev": true }, + "@types/bn.js": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", + "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "abstract-leveldown": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz", + "integrity": "sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, "commander": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", "dev": true }, - "ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "deferred-leveldown": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz", + "integrity": "sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==", "dev": true, "requires": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", + "abstract-leveldown": "~6.2.1", + "inherits": "^2.0.3" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + } + } + }, + "encoding-down": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-6.3.0.tgz", + "integrity": "sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==", + "dev": true, + "requires": { + "abstract-leveldown": "^6.2.1", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0" + } + }, + "ethereumjs-util": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz", + "integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==", + "dev": true, + "requires": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", "create-hash": "^1.1.2", - "elliptic": "^6.5.2", "ethereum-cryptography": "^0.1.3", "ethjs-util": "0.1.6", - "rlp": "^2.2.3" + "rlp": "^2.2.4" } }, "jsonfile": { @@ -15000,6 +15914,129 @@ "graceful-fs": "^4.1.6" } }, + "level-codec": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", + "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", + "dev": true, + "requires": { + "buffer": "^5.6.0" + } + }, + "level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "dev": true, + "requires": { + "errno": "~0.1.1" + } + }, + "level-iterator-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz", + "integrity": "sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.4.0", + "xtend": "^4.0.2" + } + }, + "level-mem": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-5.0.1.tgz", + "integrity": "sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg==", + "dev": true, + "requires": { + "level-packager": "^5.0.3", + "memdown": "^5.0.0" + } + }, + "level-packager": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-5.1.1.tgz", + "integrity": "sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ==", + "dev": true, + "requires": { + "encoding-down": "^6.3.0", + "levelup": "^4.3.2" + } + }, + "level-ws": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-2.0.0.tgz", + "integrity": "sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^3.1.0", + "xtend": "^4.0.1" + } + }, + "levelup": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-4.4.0.tgz", + "integrity": "sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==", + "dev": true, + "requires": { + "deferred-leveldown": "~5.3.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~4.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "memdown": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-5.1.0.tgz", + "integrity": "sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw==", + "dev": true, + "requires": { + "abstract-leveldown": "~6.2.1", + "functional-red-black-tree": "~1.0.1", + "immediate": "~3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", + "dev": true + } + } + }, + "merkle-patricia-tree": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-4.1.0.tgz", + "integrity": "sha512-vmP1J7FwIpprFMVjjSMM1JAwFce85Q+tp0TYIedYv8qaMh2oLUZ3ETXn9wbgi9S6elySzKzGa+Ai6VNKGEwSlg==", + "dev": true, + "requires": { + "@types/levelup": "^4.3.0", + "ethereumjs-util": "^7.0.8", + "level-mem": "^5.0.1", + "level-ws": "^2.0.0", + "readable-stream": "^3.6.0", + "rlp": "^2.2.3", + "semaphore-async-await": "^1.5.1" + } + }, "resolve": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", @@ -15064,6 +16101,12 @@ "requires": { "os-tmpdir": "~1.0.2" } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true } } }, @@ -15837,6 +16880,12 @@ "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", "dev": true }, + "level-concat-iterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz", + "integrity": "sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw==", + "dev": true + }, "level-errors": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", @@ -16042,6 +17091,23 @@ } } }, + "level-supports": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", + "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", + "dev": true, + "requires": { + "xtend": "^4.0.2" + }, + "dependencies": { + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, "level-ws": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", @@ -16236,6 +17302,12 @@ "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", "dev": true }, + "mcl-wasm": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.6.tgz", + "integrity": "sha512-cbRl3sUOkBeRY2hsM4t1EIln2TIdQBkSiTOqNTv/4Hu5KOECnMWCgjIf+a9Ebunyn22VKqkMF3zj6ejRzz7YBw==", + "dev": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -17619,6 +18691,12 @@ } } }, + "printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", + "dev": true + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -18147,6 +19225,12 @@ "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", "dev": true }, + "semaphore-async-await": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/semaphore-async-await/-/semaphore-async-await-1.5.1.tgz", + "integrity": "sha1-hXvvXjZEYBykuVcLh+nfXKEpdPo=", + "dev": true + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", diff --git a/package.json b/package.json index b47534a9..91f13f6d 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "ethereumjs-util": "7.0.2", "ethers": "^5.0.19", "globby": "^11.0.1", - "hardhat": "^2.0.8", + "hardhat": "^2.2.0", "hardhat-gas-reporter": "^1.0.0", "hardhat-typechain": "^0.3.3", "husky": "^4.2.5", From e6f6fce7878668d7ebce8edbc5b81144ff024408 Mon Sep 17 00:00:00 2001 From: David Racero Date: Fri, 23 Apr 2021 18:04:43 +0200 Subject: [PATCH 208/219] feat: add github actions to run tests at master and pull requests --- .github/workflows/node.js.yml | 37 + hardhat.config.ts | 1 + package-lock.json | 2311 ++++++++++----------------------- package.json | 2 +- 4 files changed, 713 insertions(+), 1638 deletions(-) create mode 100644 .github/workflows/node.js.yml diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml new file mode 100644 index 00000000..094c2263 --- /dev/null +++ b/.github/workflows/node.js.yml @@ -0,0 +1,37 @@ +name: Aave Actions + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [14.x] + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + - uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Install dependencies + run: npm ci + - name: Test + run: npm run ci:test + # - name: Coverage + # run: npm run coverage + # - uses: codecov/codecov-action@v1 + # with: + # fail_ci_if_error: true diff --git a/hardhat.config.ts b/hardhat.config.ts index 713a6733..3eaba7c0 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -15,6 +15,7 @@ import 'temp-hardhat-etherscan'; import 'hardhat-gas-reporter'; import 'hardhat-typechain'; import '@tenderly/hardhat-tenderly'; +import 'solidity-coverage'; const SKIP_LOAD = process.env.SKIP_LOAD === 'true'; const DEFAULT_BLOCK_GAS_LIMIT = 12450000; diff --git a/package-lock.json b/package-lock.json index d562af03..4b51bc02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1981,27 +1981,26 @@ } }, "@truffle/error": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@truffle/error/-/error-0.0.7.tgz", - "integrity": "sha512-UIfVKsXSXocKnn5+RNklUXNoGd/JVj7V8KmC48TQzmjU33HQI86PX0JDS7SpHMHasI3w9X//1q7Lu7nZtj3Zzg==", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@truffle/error/-/error-0.0.12.tgz", + "integrity": "sha512-kZqqnPR9YDJG7KCDOcN1qH16Qs0oz1PzF0Y93AWdhXuL9S9HYo/RUUeqGKbPpRBEZldQUS8aa4EzfK08u5pu6g==", "dev": true }, "@truffle/interface-adapter": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.3.3.tgz", - "integrity": "sha512-l3I4WFTfnBSIfG96IOBRtAIE6AHDAxcOUJE7W5zh9hocQwzQlGWc2yEyyTcLa0656TTM8RxaZZ2S/KdHHMvCaw==", + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.4.21.tgz", + "integrity": "sha512-uGU9T0a1S1f1xiTrNksd9ba+55SyU9jaCLNauFGOtppWDmjHD7dorxncEyj7lM9dcKl+w8Y+wHy79bb/LG4XFQ==", "dev": true, "requires": { - "bn.js": "^4.11.8", + "bn.js": "^5.1.3", "ethers": "^4.0.32", - "lodash": "^4.17.13", - "web3": "1.2.2" + "web3": "1.3.5" }, "dependencies": { - "@types/node": { - "version": "12.20.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.6.tgz", - "integrity": "sha512-sRVq8d+ApGslmkE9e3i+D3gFGk7aZHAT+G4cIpIEdLJYPsWiSPwcAnJEjddLQQDqV3Ra2jOclX/Sv6YrvGYiWA==", + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", "dev": true }, "elliptic": { @@ -2017,17 +2016,14 @@ "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.0" - } - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } } }, "ethers": { @@ -2045,6 +2041,14 @@ "setimmediate": "1.0.4", "uuid": "2.0.1", "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } } }, "hash.js": { @@ -2080,519 +2084,18 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", "dev": true - }, - "web3": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.2.tgz", - "integrity": "sha512-/ChbmB6qZpfGx6eNpczt5YSUBHEA5V2+iUCbn85EVb3Zv6FVxrOo5Tv7Lw0gE2tW7EEjASbCyp3mZeiZaCCngg==", - "dev": true, - "requires": { - "@types/node": "^12.6.1", - "web3-bzz": "1.2.2", - "web3-core": "1.2.2", - "web3-eth": "1.2.2", - "web3-eth-personal": "1.2.2", - "web3-net": "1.2.2", - "web3-shh": "1.2.2", - "web3-utils": "1.2.2" - } - }, - "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - } - } } } }, "@truffle/provider": { - "version": "0.1.19", - "resolved": "https://registry.npmjs.org/@truffle/provider/-/provider-0.1.19.tgz", - "integrity": "sha512-ke8iQmzW4Y99+8iff8xQcc+mCNU4AkwtaZ/iSpmVD8qpLytw8/DSNCm0RiEz9/+I93Q1zqI4Jnij/rXnkS2Njw==", + "version": "0.2.28", + "resolved": "https://registry.npmjs.org/@truffle/provider/-/provider-0.2.28.tgz", + "integrity": "sha512-lowQkQPVSnn1jG3JIrp5iTDxkHZErjjjbLsvpI1kd8sYQ5LcGorgPQVsGlhM5BfYUQCeHLeFwwFb0ghx3hisKw==", "dev": true, "requires": { - "@truffle/error": "^0.0.7", - "@truffle/interface-adapter": "^0.3.0", - "web3": "1.2.1" - }, - "dependencies": { - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true - }, - "@types/node": { - "version": "10.17.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.55.tgz", - "integrity": "sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==", - "dev": true - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } - } - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "ethers": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", - "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", - "dev": true, - "requires": { - "@types/node": "^10.3.2", - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "elliptic": "6.3.3", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.3", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - }, - "dependencies": { - "elliptic": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", - "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" - } - } - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, - "normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", - "dev": true - }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true - }, - "scrypt-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", - "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", - "dev": true - }, - "semver": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz", - "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==", - "dev": true - }, - "setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", - "dev": true - }, - "uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", - "dev": true - }, - "web3": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.1.tgz", - "integrity": "sha512-nNMzeCK0agb5i/oTWNdQ1aGtwYfXzHottFP2Dz0oGIzavPMGSKyVlr8ibVb1yK5sJBjrWVnTdGaOC2zKDFuFRw==", - "dev": true, - "requires": { - "web3-bzz": "1.2.1", - "web3-core": "1.2.1", - "web3-eth": "1.2.1", - "web3-eth-personal": "1.2.1", - "web3-net": "1.2.1", - "web3-shh": "1.2.1", - "web3-utils": "1.2.1" - } - }, - "web3-bzz": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.1.tgz", - "integrity": "sha512-LdOO44TuYbGIPfL4ilkuS89GQovxUpmLz6C1UC7VYVVRILeZS740FVB3j9V4P4FHUk1RenaDfKhcntqgVCHtjw==", - "dev": true, - "requires": { - "got": "9.6.0", - "swarm-js": "0.1.39", - "underscore": "1.9.1" - } - }, - "web3-core": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.1.tgz", - "integrity": "sha512-5ODwIqgl8oIg/0+Ai4jsLxkKFWJYE0uLuE1yUKHNVCL4zL6n3rFjRMpKPokd6id6nJCNgeA64KdWQ4XfpnjdMg==", - "dev": true, - "requires": { - "web3-core-helpers": "1.2.1", - "web3-core-method": "1.2.1", - "web3-core-requestmanager": "1.2.1", - "web3-utils": "1.2.1" - } - }, - "web3-core-helpers": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.1.tgz", - "integrity": "sha512-Gx3sTEajD5r96bJgfuW377PZVFmXIH4TdqDhgGwd2lZQCcMi+DA4TgxJNJGxn0R3aUVzyyE76j4LBrh412mXrw==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-eth-iban": "1.2.1", - "web3-utils": "1.2.1" - } - }, - "web3-core-method": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.1.tgz", - "integrity": "sha512-Ghg2WS23qi6Xj8Od3VCzaImLHseEA7/usvnOItluiIc5cKs00WYWsNy2YRStzU9a2+z8lwQywPYp0nTzR/QXdQ==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.1", - "web3-core-promievent": "1.2.1", - "web3-core-subscriptions": "1.2.1", - "web3-utils": "1.2.1" - } - }, - "web3-core-promievent": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.1.tgz", - "integrity": "sha512-IVUqgpIKoeOYblwpex4Hye6npM0aMR+kU49VP06secPeN0rHMyhGF0ZGveWBrGvf8WDPI7jhqPBFIC6Jf3Q3zw==", - "dev": true, - "requires": { - "any-promise": "1.3.0", - "eventemitter3": "3.1.2" - } - }, - "web3-core-requestmanager": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.1.tgz", - "integrity": "sha512-xfknTC69RfYmLKC+83Jz73IC3/sS2ZLhGtX33D4Q5nQ8yc39ElyAolxr9sJQS8kihOcM6u4J+8gyGMqsLcpIBg==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.1", - "web3-providers-http": "1.2.1", - "web3-providers-ipc": "1.2.1", - "web3-providers-ws": "1.2.1" - } - }, - "web3-core-subscriptions": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.1.tgz", - "integrity": "sha512-nmOwe3NsB8V8UFsY1r+sW6KjdOS68h8nuh7NzlWxBQT/19QSUGiERRTaZXWu5BYvo1EoZRMxCKyCQpSSXLc08g==", - "dev": true, - "requires": { - "eventemitter3": "3.1.2", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.1" - } - }, - "web3-eth": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.1.tgz", - "integrity": "sha512-/2xly4Yry5FW1i+uygPjhfvgUP/MS/Dk+PDqmzp5M88tS86A+j8BzKc23GrlA8sgGs0645cpZK/999LpEF5UdA==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-core": "1.2.1", - "web3-core-helpers": "1.2.1", - "web3-core-method": "1.2.1", - "web3-core-subscriptions": "1.2.1", - "web3-eth-abi": "1.2.1", - "web3-eth-accounts": "1.2.1", - "web3-eth-contract": "1.2.1", - "web3-eth-ens": "1.2.1", - "web3-eth-iban": "1.2.1", - "web3-eth-personal": "1.2.1", - "web3-net": "1.2.1", - "web3-utils": "1.2.1" - } - }, - "web3-eth-abi": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.1.tgz", - "integrity": "sha512-jI/KhU2a/DQPZXHjo2GW0myEljzfiKOn+h1qxK1+Y9OQfTcBMxrQJyH5AP89O6l6NZ1QvNdq99ThAxBFoy5L+g==", - "dev": true, - "requires": { - "ethers": "4.0.0-beta.3", - "underscore": "1.9.1", - "web3-utils": "1.2.1" - } - }, - "web3-eth-accounts": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.1.tgz", - "integrity": "sha512-26I4qq42STQ8IeKUyur3MdQ1NzrzCqPsmzqpux0j6X/XBD7EjZ+Cs0lhGNkSKH5dI3V8CJasnQ5T1mNKeWB7nQ==", - "dev": true, - "requires": { - "any-promise": "1.3.0", - "crypto-browserify": "3.12.0", - "eth-lib": "0.2.7", - "scryptsy": "2.1.0", - "semver": "6.2.0", - "underscore": "1.9.1", - "uuid": "3.3.2", - "web3-core": "1.2.1", - "web3-core-helpers": "1.2.1", - "web3-core-method": "1.2.1", - "web3-utils": "1.2.1" - }, - "dependencies": { - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - } - } - }, - "web3-eth-contract": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.1.tgz", - "integrity": "sha512-kYFESbQ3boC9bl2rYVghj7O8UKMiuKaiMkxvRH5cEDHil8V7MGEGZNH0slSdoyeftZVlaWSMqkRP/chfnKND0g==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-core": "1.2.1", - "web3-core-helpers": "1.2.1", - "web3-core-method": "1.2.1", - "web3-core-promievent": "1.2.1", - "web3-core-subscriptions": "1.2.1", - "web3-eth-abi": "1.2.1", - "web3-utils": "1.2.1" - } - }, - "web3-eth-ens": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.1.tgz", - "integrity": "sha512-lhP1kFhqZr2nnbu3CGIFFrAnNxk2veXpOXBY48Tub37RtobDyHijHgrj+xTh+mFiPokyrapVjpFsbGa+Xzye4Q==", - "dev": true, - "requires": { - "eth-ens-namehash": "2.0.8", - "underscore": "1.9.1", - "web3-core": "1.2.1", - "web3-core-helpers": "1.2.1", - "web3-core-promievent": "1.2.1", - "web3-eth-abi": "1.2.1", - "web3-eth-contract": "1.2.1", - "web3-utils": "1.2.1" - } - }, - "web3-eth-iban": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.1.tgz", - "integrity": "sha512-9gkr4QPl1jCU+wkgmZ8EwODVO3ovVj6d6JKMos52ggdT2YCmlfvFVF6wlGLwi0VvNa/p+0BjJzaqxnnG/JewjQ==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "web3-utils": "1.2.1" - } - }, - "web3-eth-personal": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.1.tgz", - "integrity": "sha512-RNDVSiaSoY4aIp8+Hc7z+X72H7lMb3fmAChuSBADoEc7DsJrY/d0R5qQDK9g9t2BO8oxgLrLNyBP/9ub2Hc6Bg==", - "dev": true, - "requires": { - "web3-core": "1.2.1", - "web3-core-helpers": "1.2.1", - "web3-core-method": "1.2.1", - "web3-net": "1.2.1", - "web3-utils": "1.2.1" - } - }, - "web3-net": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.1.tgz", - "integrity": "sha512-Yt1Bs7WgnLESPe0rri/ZoPWzSy55ovioaP35w1KZydrNtQ5Yq4WcrAdhBzcOW7vAkIwrsLQsvA+hrOCy7mNauw==", - "dev": true, - "requires": { - "web3-core": "1.2.1", - "web3-core-method": "1.2.1", - "web3-utils": "1.2.1" - } - }, - "web3-providers-http": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.1.tgz", - "integrity": "sha512-BDtVUVolT9b3CAzeGVA/np1hhn7RPUZ6YYGB/sYky+GjeO311Yoq8SRDUSezU92x8yImSC2B+SMReGhd1zL+bQ==", - "dev": true, - "requires": { - "web3-core-helpers": "1.2.1", - "xhr2-cookies": "1.1.0" - } - }, - "web3-providers-ipc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.1.tgz", - "integrity": "sha512-oPEuOCwxVx8L4CPD0TUdnlOUZwGBSRKScCz/Ws2YHdr9Ium+whm+0NLmOZjkjQp5wovQbyBzNa6zJz1noFRvFA==", - "dev": true, - "requires": { - "oboe": "2.1.4", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.1" - } - }, - "web3-providers-ws": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.1.tgz", - "integrity": "sha512-oqsQXzu+ejJACVHy864WwIyw+oB21nw/pI65/sD95Zi98+/HQzFfNcIFneF1NC4bVF3VNX4YHTNq2I2o97LAiA==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.1", - "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" - } - }, - "web3-shh": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.1.tgz", - "integrity": "sha512-/3Cl04nza5kuFn25bV3FJWa0s3Vafr5BlT933h26xovQ6HIIz61LmvNQlvX1AhFL+SNJOTcQmK1SM59vcyC8bA==", - "dev": true, - "requires": { - "web3-core": "1.2.1", - "web3-core-method": "1.2.1", - "web3-core-subscriptions": "1.2.1", - "web3-net": "1.2.1" - } - }, - "web3-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.1.tgz", - "integrity": "sha512-Mrcn3l58L+yCKz3zBryM6JZpNruWuT0OCbag8w+reeNROSGVlXzUQkU+gtAwc9JCZ7tKUyg67+2YUGqUjVcyBA==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.9.1", - "utf8": "3.0.0" - } - } + "@truffle/error": "^0.0.12", + "@truffle/interface-adapter": "^0.4.21", + "web3": "1.3.5" } }, "@typechain/ethers-v4": { @@ -2844,46 +2347,6 @@ "@types/underscore": "*" } }, - "@web3-js/scrypt-shim": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz", - "integrity": "sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw==", - "dev": true, - "requires": { - "scryptsy": "^2.1.0", - "semver": "^6.3.0" - } - }, - "@web3-js/websocket": { - "version": "1.0.30", - "resolved": "https://registry.npmjs.org/@web3-js/websocket/-/websocket-1.0.30.tgz", - "integrity": "sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA==", - "dev": true, - "requires": { - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "nan": "^2.14.0", - "typedarray-to-buffer": "^3.1.5", - "yaeti": "^0.0.6" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, "@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -3008,12 +2471,6 @@ "color-convert": "^1.9.0" } }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", - "dev": true - }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -3071,6 +2528,12 @@ "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", "dev": true }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", + "dev": true + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -3164,6 +2627,15 @@ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true }, + "available-typed-arrays": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", + "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", + "dev": true, + "requires": { + "array-filter": "^1.0.0" + } + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -3592,6 +3064,15 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, + "bufferutil": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz", + "integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==", + "dev": true, + "requires": { + "node-gyp-build": "^4.2.0" + } + }, "buidler-typechain": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/buidler-typechain/-/buidler-typechain-0.1.1.tgz", @@ -3777,6 +3258,31 @@ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, + "cids": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", + "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "class-is": "^1.1.0", + "multibase": "~0.6.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.15" + }, + "dependencies": { + "multicodec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", + "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", + "dev": true, + "requires": { + "buffer": "^5.6.0", + "varint": "^5.0.0" + } + } + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3787,6 +3293,12 @@ "safe-buffer": "^5.0.1" } }, + "class-is": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", + "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", + "dev": true + }, "cli-table3": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", @@ -3993,6 +3505,17 @@ } } }, + "content-hash": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", + "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", + "dev": true, + "requires": { + "cids": "^0.7.1", + "multicodec": "^0.5.5", + "multihashes": "^0.4.15" + } + }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", @@ -5435,9 +4958,9 @@ "dev": true }, "eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", + "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", "dev": true }, "evp_bytestokey": { @@ -5871,6 +5394,12 @@ "is-callable": "^1.1.3" } }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -6011,16 +5540,45 @@ "dev": true }, "ganache-cli": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.9.0.tgz", - "integrity": "sha512-ZdL6kPrApXF/O+f6uU431OJcwxMk69H3KPDSHHrMP82ZvZRNpDHbR+rVv7XX/YUeoQ5q6nZ2AFiGiFAVn9pfzA==", + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.12.2.tgz", + "integrity": "sha512-bnmwnJDBDsOWBUP8E/BExWf85TsdDEFelQSzihSJm9VChVO1SHp94YXLP5BlA4j/OTxp0wR4R1Tje9OHOuAJVw==", "dev": true, "requires": { - "ethereumjs-util": "6.1.0", + "ethereumjs-util": "6.2.1", "source-map-support": "0.5.12", "yargs": "13.2.4" }, "dependencies": { + "@types/bn.js": { + "version": "4.11.6", + "bundled": true, + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "14.11.2", + "bundled": true, + "dev": true + }, + "@types/pbkdf2": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/secp256k1": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "requires": { + "@types/node": "*" + } + }, "ansi-regex": { "version": "4.1.0", "bundled": true, @@ -6034,24 +5592,21 @@ "color-convert": "^1.9.0" } }, - "bindings": { - "version": "1.5.0", - "bundled": true, - "dev": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bip66": { - "version": "1.1.5", + "base-x": { + "version": "3.0.8", "bundled": true, "dev": true, "requires": { "safe-buffer": "^5.0.1" } }, + "blakejs": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, "bn.js": { - "version": "4.11.8", + "version": "4.11.9", "bundled": true, "dev": true }, @@ -6073,6 +5628,24 @@ "safe-buffer": "^5.0.1" } }, + "bs58": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "requires": { + "base-x": "^3.0.2" + } + }, + "bs58check": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "requires": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, "buffer-from": { "version": "1.1.1", "bundled": true, @@ -6162,18 +5735,8 @@ "bundled": true, "dev": true }, - "drbg.js": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "browserify-aes": "^1.0.6", - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4" - } - }, "elliptic": { - "version": "6.5.0", + "version": "6.5.3", "bundled": true, "dev": true, "requires": { @@ -6192,25 +5755,47 @@ "dev": true }, "end-of-stream": { - "version": "1.4.1", + "version": "1.4.4", "bundled": true, "dev": true, "requires": { "once": "^1.4.0" } }, - "ethereumjs-util": { - "version": "6.1.0", + "ethereum-cryptography": { + "version": "0.1.3", "bundled": true, "dev": true, "requires": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "ethereumjs-util": { + "version": "6.2.1", + "bundled": true, + "dev": true, + "requires": { + "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", "ethjs-util": "0.1.6", - "keccak": "^1.0.2", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1", - "secp256k1": "^3.0.1" + "rlp": "^2.2.3" } }, "ethjs-util": { @@ -6245,11 +5830,6 @@ "strip-eof": "^1.0.0" } }, - "file-uri-to-path": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, "find-up": { "version": "3.0.0", "bundled": true, @@ -6272,12 +5852,13 @@ } }, "hash-base": { - "version": "3.0.4", + "version": "3.1.0", "bundled": true, "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" } }, "hash.js": { @@ -6330,14 +5911,12 @@ "dev": true }, "keccak": { - "version": "1.4.0", + "version": "3.0.1", "bundled": true, "dev": true, "requires": { - "bindings": "^1.2.1", - "inherits": "^2.0.3", - "nan": "^2.2.1", - "safe-buffer": "^5.1.0" + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" } }, "lcid": { @@ -6400,13 +5979,18 @@ "bundled": true, "dev": true }, - "nan": { - "version": "2.14.0", + "nice-try": { + "version": "1.0.5", "bundled": true, "dev": true }, - "nice-try": { - "version": "1.0.5", + "node-addon-api": { + "version": "2.0.2", + "bundled": true, + "dev": true + }, + "node-gyp-build": { + "version": "4.2.3", "bundled": true, "dev": true }, @@ -6452,7 +6036,7 @@ "dev": true }, "p-limit": { - "version": "2.2.0", + "version": "2.3.0", "bundled": true, "dev": true, "requires": { @@ -6482,6 +6066,18 @@ "bundled": true, "dev": true }, + "pbkdf2": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "pump": { "version": "3.0.0", "bundled": true, @@ -6491,6 +6087,24 @@ "once": "^1.3.1" } }, + "randombytes": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "bundled": true, + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "require-directory": { "version": "2.1.1", "bundled": true, @@ -6511,36 +6125,35 @@ } }, "rlp": { - "version": "2.2.3", + "version": "2.2.6", "bundled": true, "dev": true, "requires": { - "bn.js": "^4.11.1", - "safe-buffer": "^5.1.1" + "bn.js": "^4.11.1" } }, "safe-buffer": { - "version": "5.2.0", + "version": "5.2.1", + "bundled": true, + "dev": true + }, + "scrypt-js": { + "version": "3.0.1", "bundled": true, "dev": true }, "secp256k1": { - "version": "3.7.1", + "version": "4.0.2", "bundled": true, "dev": true, "requires": { - "bindings": "^1.5.0", - "bip66": "^1.1.5", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "drbg.js": "^1.0.1", - "elliptic": "^6.4.1", - "nan": "^2.14.0", - "safe-buffer": "^5.1.2" + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" } }, "semver": { - "version": "5.7.0", + "version": "5.7.1", "bundled": true, "dev": true }, @@ -6549,6 +6162,11 @@ "bundled": true, "dev": true }, + "setimmediate": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, "sha.js": { "version": "2.4.11", "bundled": true, @@ -6572,7 +6190,7 @@ "dev": true }, "signal-exit": { - "version": "3.0.2", + "version": "3.0.3", "bundled": true, "dev": true }, @@ -6600,6 +6218,14 @@ "strip-ansi": "^5.1.0" } }, + "string_decoder": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, "strip-ansi": { "version": "5.2.0", "bundled": true, @@ -6621,6 +6247,11 @@ "is-hex-prefixed": "1.0.0" } }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, "which": { "version": "1.3.1", "bundled": true, @@ -6673,7 +6304,7 @@ } }, "yargs-parser": { - "version": "13.1.1", + "version": "13.1.2", "bundled": true, "dev": true, "requires": { @@ -16473,6 +16104,15 @@ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true }, + "is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -16563,6 +16203,12 @@ "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", "dev": true }, + "is-generator-function": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz", + "integrity": "sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ==", + "dev": true + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -16676,6 +16322,19 @@ "has-symbols": "^1.0.1" } }, + "is-typed-array": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", + "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.0-next.2", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -17793,9 +17452,9 @@ } }, "mock-fs": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.13.0.tgz", - "integrity": "sha512-DD0vOdofJdoaRNtnWcrXe6RQbpHkPPmtqGq14uRX0F8ZKJ5nv89CVTYl/BZdppDxBDaV0hl75htg3abpEWlPZA==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.14.0.tgz", + "integrity": "sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw==", "dev": true }, "mri": { @@ -17810,6 +17469,48 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "multibase": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", + "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", + "dev": true, + "requires": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + }, + "multicodec": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", + "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", + "dev": true, + "requires": { + "varint": "^5.0.0" + } + }, + "multihashes": { + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", + "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "multibase": "^0.7.0", + "varint": "^5.0.0" + }, + "dependencies": { + "multibase": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", + "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", + "dev": true, + "requires": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + } + } + }, "multimatch": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", @@ -18080,9 +17781,9 @@ "dev": true }, "oboe": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.4.tgz", - "integrity": "sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY=", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.5.tgz", + "integrity": "sha1-VVQoTFQ6ImbXo48X4HOCH73jk80=", "dev": true, "requires": { "http-https": "^1.0.0" @@ -18827,12 +18528,6 @@ "safe-buffer": "^5.1.0" } }, - "randomhex": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", - "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=", - "dev": true - }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -19184,21 +18879,6 @@ "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", "dev": true }, - "scrypt-shim": { - "version": "github:web3-js/scrypt-shim#aafdadda13e660e25e1c525d1f5b2443f5eb1ebb", - "from": "github:web3-js/scrypt-shim", - "dev": true, - "requires": { - "scryptsy": "^2.1.0", - "semver": "^6.3.0" - } - }, - "scryptsy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz", - "integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==", - "dev": true - }, "secp256k1": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", @@ -19501,18 +19181,18 @@ "dev": true }, "solidity-coverage": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.10.tgz", - "integrity": "sha512-F98rYoD3bscB9qIJJrqkk+o93GbOWTT54VgfO97PrcWAenOFIC1EI5DzGJSrMvmFFfr8fsMPR89on6JR0Xf/Ig==", + "version": "0.7.16", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.16.tgz", + "integrity": "sha512-ttBOStywE6ZOTJmmABSg4b8pwwZfYKG8zxu40Nz+sRF5bQX7JULXWj/XbX0KXps3Fsp8CJXg8P29rH3W54ipxw==", "dev": true, "requires": { - "@solidity-parser/parser": "^0.7.0", - "@truffle/provider": "^0.1.17", + "@solidity-parser/parser": "^0.12.0", + "@truffle/provider": "^0.2.24", "chalk": "^2.4.2", "death": "^1.1.0", "detect-port": "^1.3.0", "fs-extra": "^8.1.0", - "ganache-cli": "6.9.0", + "ganache-cli": "^6.11.0", "ghost-testrpc": "^0.0.2", "global-modules": "^2.0.0", "globby": "^10.0.1", @@ -19522,14 +19202,15 @@ "pify": "^4.0.1", "recursive-readdir": "^2.2.2", "sc-istanbul": "^0.4.5", + "semver": "^7.3.4", "shelljs": "^0.8.3", - "web3": "1.2.6" + "web3-utils": "^1.3.0" }, "dependencies": { "@solidity-parser/parser": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.7.1.tgz", - "integrity": "sha512-5ma2uuwPAEX1TPl2rAPAAuGlBkKnn2oUKQvnhTFlDIB8U/KDWX77FpHtL6Rcz+OwqSCWx9IClxACgyIEJ/GhIw==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.12.1.tgz", + "integrity": "sha512-ikxVpwskNxEp2fvYS1BdRImnevHmM97zdPFBa1cVtjtNpoqCm/EmljATTZk0s9G/zsN5ZbPf9OAIAW4gbBJiRA==", "dev": true }, "fs-extra": { @@ -19559,11 +19240,35 @@ "slash": "^3.0.0" } }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, @@ -19814,14 +19519,13 @@ } }, "swarm-js": { - "version": "0.1.39", - "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.39.tgz", - "integrity": "sha512-QLMqL2rzF6n5s50BptyD6Oi0R1aWlJC5Y17SRIVXRj6OR1DRIPM7nepvrxxkjA1zNzFz6mUOMjfeqeDaWB7OOg==", + "version": "0.1.40", + "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.40.tgz", + "integrity": "sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA==", "dev": true, "requires": { "bluebird": "^3.5.0", "buffer": "^5.0.5", - "decompress": "^4.0.0", "eth-lib": "^0.1.26", "fs-extra": "^4.0.2", "got": "^7.1.0", @@ -19830,7 +19534,7 @@ "mock-fs": "^4.1.0", "setimmediate": "^1.0.5", "tar": "^4.0.2", - "xhr-request-promise": "^0.1.2" + "xhr-request": "^1.0.1" }, "dependencies": { "eth-lib": { @@ -20414,9 +20118,9 @@ "dev": true }, "uglify-js": { - "version": "3.13.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.2.tgz", - "integrity": "sha512-SbMu4D2Vo95LMC/MetNaso1194M1htEA+JrqE9Hk+G2DhI+itfS9TRu9ZKeCahLDNa/J3n4MqUJ/fOHMzQpRWw==", + "version": "3.13.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.4.tgz", + "integrity": "sha512-kv7fCkIXyQIilD5/yQy8O+uagsYIOt5cZvs890W40/e/rvjMSzJw81o9Bg0tkURxzZBROtDQhW2LFjOGoK3RZw==", "dev": true, "optional": true }, @@ -20514,12 +20218,35 @@ "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", "dev": true }, + "utf-8-validate": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.4.tgz", + "integrity": "sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==", + "dev": true, + "requires": { + "node-gyp-build": "^4.2.0" + } + }, "utf8": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", "dev": true }, + "util": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz", + "integrity": "sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -20561,6 +20288,12 @@ "spdx-expression-parse": "^3.0.0" } }, + "varint": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", + "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", + "dev": true + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -20579,483 +20312,28 @@ } }, "web3": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.6.tgz", - "integrity": "sha512-tpu9fLIComgxGrFsD8LUtA4s4aCZk7px8UfcdEy6kS2uDi/ZfR07KJqpXZMij7Jvlq+cQrTAhsPSiBVvoMaivA==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.3.5.tgz", + "integrity": "sha512-UyQW/MT5EIGBrXPCh/FDIaD7RtJTn5/rJUNw2FOglp0qoXnCQHNKvntiR1ylztk05fYxIF6UgsC76IrazlKJjw==", "dev": true, "requires": { - "@types/node": "^12.6.1", - "web3-bzz": "1.2.6", - "web3-core": "1.2.6", - "web3-eth": "1.2.6", - "web3-eth-personal": "1.2.6", - "web3-net": "1.2.6", - "web3-shh": "1.2.6", - "web3-utils": "1.2.6" + "web3-bzz": "1.3.5", + "web3-core": "1.3.5", + "web3-eth": "1.3.5", + "web3-eth-personal": "1.3.5", + "web3-net": "1.3.5", + "web3-shh": "1.3.5", + "web3-utils": "1.3.5" }, "dependencies": { - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true - }, - "@types/node": { - "version": "12.20.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.6.tgz", - "integrity": "sha512-sRVq8d+ApGslmkE9e3i+D3gFGk7aZHAT+G4cIpIEdLJYPsWiSPwcAnJEjddLQQDqV3Ra2jOclX/Sv6YrvGYiWA==", - "dev": true - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } - } - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "ethers": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", - "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", - "dev": true, - "requires": { - "@types/node": "^10.3.2", - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "elliptic": "6.3.3", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.3", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - }, - "dependencies": { - "@types/node": { - "version": "10.17.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.55.tgz", - "integrity": "sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==", - "dev": true - }, - "elliptic": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", - "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" - } - } - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, - "normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", - "dev": true - }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true - }, - "scrypt-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", - "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", - "dev": true - }, - "setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", - "dev": true - }, - "uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", - "dev": true - }, - "web3-bzz": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.6.tgz", - "integrity": "sha512-9NiHLlxdI1XeFtbPJAmi2jnnIHVF+GNy517wvOS72P7ZfuJTPwZaSNXfT01vWgPPE9R96/uAHDWHOg+T4WaDQQ==", - "dev": true, - "requires": { - "@types/node": "^10.12.18", - "got": "9.6.0", - "swarm-js": "0.1.39", - "underscore": "1.9.1" - }, - "dependencies": { - "@types/node": { - "version": "10.17.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.55.tgz", - "integrity": "sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==", - "dev": true - } - } - }, - "web3-core": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.6.tgz", - "integrity": "sha512-y/QNBFtr5cIR8vxebnotbjWJpOnO8LDYEAzZjeRRUJh2ijmhjoYk7dSNx9ExgC0UCfNFRoNCa9dGRu/GAxwRlw==", - "dev": true, - "requires": { - "@types/bn.js": "^4.11.4", - "@types/node": "^12.6.1", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-core-requestmanager": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-core-helpers": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.6.tgz", - "integrity": "sha512-gYKWmC2HmO7RcDzpo4L1K8EIoy5L8iubNDuTC6q69UxczwqKF/Io0kbK/1Z10Av++NlzOSiuyGp2gc4t4UOsDw==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-eth-iban": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-core-method": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.6.tgz", - "integrity": "sha512-r2dzyPEonqkBg7Mugq5dknhV5PGaZTHBZlS/C+aMxNyQs3T3eaAsCTqlQDitwNUh/sUcYPEGF0Vo7ahYK4k91g==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6", - "web3-core-promievent": "1.2.6", - "web3-core-subscriptions": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-core-promievent": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.6.tgz", - "integrity": "sha512-km72kJef/qtQNiSjDJJVHIZvoVOm6ytW3FCYnOcCs7RIkviAb5JYlPiye0o4pJOLzCXYID7DK7Q9bhY8qWb1lw==", - "dev": true, - "requires": { - "any-promise": "1.3.0", - "eventemitter3": "3.1.2" - } - }, - "web3-core-requestmanager": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.6.tgz", - "integrity": "sha512-QU2cbsj9Dm0r6om40oSwk8Oqbp3wTa08tXuMpSmeOTkGZ3EMHJ1/4LiJ8shwg1AvPMrKVU0Nri6+uBNCdReZ+g==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6", - "web3-providers-http": "1.2.6", - "web3-providers-ipc": "1.2.6", - "web3-providers-ws": "1.2.6" - } - }, - "web3-core-subscriptions": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.6.tgz", - "integrity": "sha512-M0PzRrP2Ct13x3wPulFtc5kENH4UtnPxO9YxkfQlX2WRKENWjt4Rfq+BCVGYEk3rTutDfWrjfzjmqMRvXqEY5Q==", - "dev": true, - "requires": { - "eventemitter3": "3.1.2", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6" - } - }, - "web3-eth": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.6.tgz", - "integrity": "sha512-ROWlDPzh4QX6tlGGGlAK6X4kA2n0/cNj/4kb0nNVWkRouGmYO0R8k6s47YxYHvGiXt0s0++FUUv5vAbWovtUQw==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-core-subscriptions": "1.2.6", - "web3-eth-abi": "1.2.6", - "web3-eth-accounts": "1.2.6", - "web3-eth-contract": "1.2.6", - "web3-eth-ens": "1.2.6", - "web3-eth-iban": "1.2.6", - "web3-eth-personal": "1.2.6", - "web3-net": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-eth-abi": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.6.tgz", - "integrity": "sha512-w9GAyyikn8nSifSDZxAvU9fxtQSX+W2xQWMmrtTXmBGCaE4/ywKOSPAO78gq8AoU4Wq5yqVGKZLLbfpt7/sHlA==", - "dev": true, - "requires": { - "ethers": "4.0.0-beta.3", - "underscore": "1.9.1", - "web3-utils": "1.2.6" - } - }, - "web3-eth-accounts": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.6.tgz", - "integrity": "sha512-cDVtonHRgzqi/ZHOOf8kfCQWFEipcfQNAMzXIaKZwc0UUD9mgSI5oJrN45a89Ze+E6Lz9m77cDG5Ax9zscSkcw==", - "dev": true, - "requires": { - "@web3-js/scrypt-shim": "^0.1.0", - "any-promise": "1.3.0", - "crypto-browserify": "3.12.0", - "eth-lib": "^0.2.8", - "ethereumjs-common": "^1.3.2", - "ethereumjs-tx": "^2.1.1", - "underscore": "1.9.1", - "uuid": "3.3.2", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-utils": "1.2.6" - }, - "dependencies": { - "eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - } - } - }, - "web3-eth-contract": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.6.tgz", - "integrity": "sha512-ak4xbHIhWgsbdPCkSN+HnQc1SH4c856y7Ly+S57J/DQVzhFZemK5HvWdpwadJrQTcHET3ZeId1vq3kmW7UYodw==", - "dev": true, - "requires": { - "@types/bn.js": "^4.11.4", - "underscore": "1.9.1", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-core-promievent": "1.2.6", - "web3-core-subscriptions": "1.2.6", - "web3-eth-abi": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-eth-ens": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.6.tgz", - "integrity": "sha512-8UEqt6fqR/dji/jBGPFAyBs16OJjwi0t2dPWXPyGXmty/fH+osnXwWXE4HRUyj4xuafiM5P1YkXMsPhKEadjiw==", - "dev": true, - "requires": { - "eth-ens-namehash": "2.0.8", - "underscore": "1.9.1", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-promievent": "1.2.6", - "web3-eth-abi": "1.2.6", - "web3-eth-contract": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-eth-iban": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.6.tgz", - "integrity": "sha512-TPMc3BW9Iso7H+9w+ytbqHK9wgOmtocyCD3PaAe5Eie50KQ/j7ThA60dGJnxItVo6yyRv5pZAYxPVob9x/fJlg==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "web3-utils": "1.2.6" - } - }, - "web3-eth-personal": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.6.tgz", - "integrity": "sha512-T2NUkh1plY8d7wePXSoHnaiKOd8dLNFaQfgBl9JHU6S7IJrG9jnYD9bVxLEgRUfHs9gKf9tQpDf7AcPFdq/A8g==", - "dev": true, - "requires": { - "@types/node": "^12.6.1", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-net": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-net": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.6.tgz", - "integrity": "sha512-hsNHAPddrhgjWLmbESW0KxJi2GnthPcow0Sqpnf4oB6+/+ZnQHU9OsIyHb83bnC1OmunrK2vf9Ye2mLPdFIu3A==", - "dev": true, - "requires": { - "web3-core": "1.2.6", - "web3-core-method": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-providers-http": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.6.tgz", - "integrity": "sha512-2+SaFCspb5f82QKuHB3nEPQOF9iSWxRf7c18fHtmnLNVkfG9SwLN1zh67bYn3tZGUdOI3gj8aX4Uhfpwx9Ezpw==", - "dev": true, - "requires": { - "web3-core-helpers": "1.2.6", - "xhr2-cookies": "1.1.0" - } - }, - "web3-providers-ipc": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.6.tgz", - "integrity": "sha512-b0Es+/GTZyk5FG3SgUDW+2/mBwJAXWt5LuppODptiOas8bB2khLjG6+Gm1K4uwOb+1NJGPt5mZZ8Wi7vibtQ+A==", - "dev": true, - "requires": { - "oboe": "2.1.4", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6" - } - }, - "web3-providers-ws": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.6.tgz", - "integrity": "sha512-20waSYX+gb5M5yKhug5FIwxBBvkKzlJH7sK6XEgdOx6BZ9YYamLmvg9wcRVtnSZO8hV/3cWenO/tRtTrHVvIgQ==", - "dev": true, - "requires": { - "@web3-js/websocket": "^1.0.29", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6" - } - }, - "web3-shh": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.6.tgz", - "integrity": "sha512-rouWyOOM6YMbLQd65grpj8BBezQfgNeRRX+cGyW4xsn6Xgu+B73Zvr6OtA/ftJwwa9bqHGpnLrrLMeWyy4YLUw==", - "dev": true, - "requires": { - "web3-core": "1.2.6", - "web3-core-method": "1.2.6", - "web3-core-subscriptions": "1.2.6", - "web3-net": "1.2.6" - } - }, "web3-utils": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.6.tgz", - "integrity": "sha512-8/HnqG/l7dGmKMgEL9JeKPTtjScxOePTzopv5aaKFExPfaBrYRkgoMqhoowCiAl/s16QaTn4DoIF1QC4YsT7Mg==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", + "integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==", "dev": true, "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", "ethereum-bloom-filters": "^1.0.6", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", @@ -21067,14 +20345,14 @@ } }, "web3-bzz": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.2.tgz", - "integrity": "sha512-b1O2ObsqUN1lJxmFSjvnEC4TsaCbmh7Owj3IAIWTKqL9qhVgx7Qsu5O9cD13pBiSPNZJ68uJPaKq380QB4NWeA==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.3.5.tgz", + "integrity": "sha512-XiEUAbB1uKm/agqfwBsCW8fbw+sma85TfwuDpdcy591vinVk0S9TfWgLxro6v1KJ6nSELySIbKGbAJbh2GSyxw==", "dev": true, "requires": { - "@types/node": "^10.12.18", + "@types/node": "^12.12.6", "got": "9.6.0", - "swarm-js": "0.1.39", + "swarm-js": "^0.1.40", "underscore": "1.9.1" }, "dependencies": { @@ -21085,9 +20363,9 @@ "dev": true }, "@types/node": { - "version": "10.17.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.55.tgz", - "integrity": "sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==", + "version": "12.20.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.10.tgz", + "integrity": "sha512-TxCmnSSppKBBOzYzPR2BR25YlX5Oay8z2XGwFBInuA/Co0V9xJhLlW4kjbxKtgeNo3NOMbQP1A5Rc03y+XecPw==", "dev": true }, "cacheable-request": { @@ -21171,50 +20449,34 @@ } }, "web3-core": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.2.tgz", - "integrity": "sha512-miHAX3qUgxV+KYfaOY93Hlc3kLW2j5fH8FJy6kSxAv+d4d5aH0wwrU2IIoJylQdT+FeenQ38sgsCnFu9iZ1hCQ==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.3.5.tgz", + "integrity": "sha512-VQjTvnGTqJwDwjKEHSApea3RmgtFGLDSJ6bqrOyHROYNyTyKYjFQ/drG9zs3rjDkND9mgh8foI1ty37Qua3QCQ==", "dev": true, "requires": { - "@types/bn.js": "^4.11.4", - "@types/node": "^12.6.1", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-core-requestmanager": "1.2.2", - "web3-utils": "1.2.2" + "@types/bn.js": "^4.11.5", + "@types/node": "^12.12.6", + "bignumber.js": "^9.0.0", + "web3-core-helpers": "1.3.5", + "web3-core-method": "1.3.5", + "web3-core-requestmanager": "1.3.5", + "web3-utils": "1.3.5" }, "dependencies": { "@types/node": { - "version": "12.20.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.6.tgz", - "integrity": "sha512-sRVq8d+ApGslmkE9e3i+D3gFGk7aZHAT+G4cIpIEdLJYPsWiSPwcAnJEjddLQQDqV3Ra2jOclX/Sv6YrvGYiWA==", + "version": "12.20.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.10.tgz", + "integrity": "sha512-TxCmnSSppKBBOzYzPR2BR25YlX5Oay8z2XGwFBInuA/Co0V9xJhLlW4kjbxKtgeNo3NOMbQP1A5Rc03y+XecPw==", "dev": true }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", + "integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==", "dev": true, "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", "ethereum-bloom-filters": "^1.0.6", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", @@ -21226,41 +20488,24 @@ } }, "web3-core-helpers": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.2.tgz", - "integrity": "sha512-HJrRsIGgZa1jGUIhvGz4S5Yh6wtOIo/TMIsSLe+Xay+KVnbseJpPprDI5W3s7H2ODhMQTbogmmUFquZweW2ImQ==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.3.5.tgz", + "integrity": "sha512-HYh3ix5FjysgT0jyzD8s/X5ym0b4BGU7I2QtuBiydMnE0mQEWy7GcT9XKpTySA8FTOHHIAQYvQS07DN/ky3UzA==", "dev": true, "requires": { "underscore": "1.9.1", - "web3-eth-iban": "1.2.2", - "web3-utils": "1.2.2" + "web3-eth-iban": "1.3.5", + "web3-utils": "1.3.5" }, "dependencies": { - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", + "integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==", "dev": true, "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", "ethereum-bloom-filters": "^1.0.6", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", @@ -21272,43 +20517,27 @@ } }, "web3-core-method": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.2.tgz", - "integrity": "sha512-szR4fDSBxNHaF1DFqE+j6sFR/afv9Aa36OW93saHZnrh+iXSrYeUUDfugeNcRlugEKeUCkd4CZylfgbK2SKYJA==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.3.5.tgz", + "integrity": "sha512-hCbmgQ+At6OTuaNGAdjXMsCr4eUCmp9yGKSuaB5HdkNVDpqFso4HHjVxcjNrTyJp3OZnyjKBzQzK1ZWLpLl84Q==", "dev": true, "requires": { + "@ethersproject/transactions": "^5.0.0-beta.135", "underscore": "1.9.1", - "web3-core-helpers": "1.2.2", - "web3-core-promievent": "1.2.2", - "web3-core-subscriptions": "1.2.2", - "web3-utils": "1.2.2" + "web3-core-helpers": "1.3.5", + "web3-core-promievent": "1.3.5", + "web3-core-subscriptions": "1.3.5", + "web3-utils": "1.3.5" }, "dependencies": { - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", + "integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==", "dev": true, "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", "ethereum-bloom-filters": "^1.0.6", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", @@ -21320,85 +20549,68 @@ } }, "web3-core-promievent": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.2.tgz", - "integrity": "sha512-tKvYeT8bkUfKABcQswK6/X79blKTKYGk949urZKcLvLDEaWrM3uuzDwdQT3BNKzQ3vIvTggFPX9BwYh0F1WwqQ==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.3.5.tgz", + "integrity": "sha512-K0j8x3ZJr0eAyNvyUCxOUsSTd4hco0/9nxxlyOuijcsa6YV8l9NL6eqhniWbSyxCJT8ka5Mb7yAiUZe69EDLBQ==", "dev": true, "requires": { - "any-promise": "1.3.0", - "eventemitter3": "3.1.2" + "eventemitter3": "4.0.4" } }, "web3-core-requestmanager": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.2.tgz", - "integrity": "sha512-a+gSbiBRHtHvkp78U2bsntMGYGF2eCb6219aMufuZWeAZGXJ63Wc2321PCbA8hF9cQrZI4EoZ4kVLRI4OF15Hw==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.3.5.tgz", + "integrity": "sha512-9l294U3Ga8qmvv8E37BqjQREfMs+kFnkU3PY28g9DZGYzKvl3V1dgDYqxyrOBdCFhc7rNSpHdgC4PrVHjouspg==", "dev": true, "requires": { "underscore": "1.9.1", - "web3-core-helpers": "1.2.2", - "web3-providers-http": "1.2.2", - "web3-providers-ipc": "1.2.2", - "web3-providers-ws": "1.2.2" + "util": "^0.12.0", + "web3-core-helpers": "1.3.5", + "web3-providers-http": "1.3.5", + "web3-providers-ipc": "1.3.5", + "web3-providers-ws": "1.3.5" } }, "web3-core-subscriptions": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.2.tgz", - "integrity": "sha512-QbTgigNuT4eicAWWr7ahVpJyM8GbICsR1Ys9mJqzBEwpqS+RXTRVSkwZ2IsxO+iqv6liMNwGregbJLq4urMFcQ==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.3.5.tgz", + "integrity": "sha512-6mtXdaEB1V1zKLqYBq7RF2W75AK5ZJNGpW6QYC7Zvbku7zq1ZlgaUkJo88JKMWJ7etfaHaYqQ/7VveHk5sQynA==", "dev": true, "requires": { - "eventemitter3": "3.1.2", + "eventemitter3": "4.0.4", "underscore": "1.9.1", - "web3-core-helpers": "1.2.2" + "web3-core-helpers": "1.3.5" } }, "web3-eth": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.2.tgz", - "integrity": "sha512-UXpC74mBQvZzd4b+baD4Ocp7g+BlwxhBHumy9seyE/LMIcMlePXwCKzxve9yReNpjaU16Mmyya6ZYlyiKKV8UA==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.3.5.tgz", + "integrity": "sha512-5qqDPMMD+D0xRqOV2ePU2G7/uQmhn0FgCEhFzKDMHrssDQJyQLW/VgfA0NLn64lWnuUrGnQStGvNxrWf7MgsfA==", "dev": true, "requires": { "underscore": "1.9.1", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-core-subscriptions": "1.2.2", - "web3-eth-abi": "1.2.2", - "web3-eth-accounts": "1.2.2", - "web3-eth-contract": "1.2.2", - "web3-eth-ens": "1.2.2", - "web3-eth-iban": "1.2.2", - "web3-eth-personal": "1.2.2", - "web3-net": "1.2.2", - "web3-utils": "1.2.2" + "web3-core": "1.3.5", + "web3-core-helpers": "1.3.5", + "web3-core-method": "1.3.5", + "web3-core-subscriptions": "1.3.5", + "web3-eth-abi": "1.3.5", + "web3-eth-accounts": "1.3.5", + "web3-eth-contract": "1.3.5", + "web3-eth-ens": "1.3.5", + "web3-eth-iban": "1.3.5", + "web3-eth-personal": "1.3.5", + "web3-net": "1.3.5", + "web3-utils": "1.3.5" }, "dependencies": { - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", + "integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==", "dev": true, "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", "ethereum-bloom-filters": "^1.0.6", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", @@ -21410,171 +20622,70 @@ } }, "web3-eth-abi": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.2.tgz", - "integrity": "sha512-Yn/ZMgoOLxhTVxIYtPJ0eS6pnAnkTAaJgUJh1JhZS4ekzgswMfEYXOwpMaD5eiqPJLpuxmZFnXnBZlnQ1JMXsw==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.3.5.tgz", + "integrity": "sha512-bkbG2v/mOW5DH6rF/SEgqunusjYoEi2IBw+fkmD3rzWDaEY7+/i1xY94AeO257d06QMgld75GtV/N+aEs7A6vQ==", "dev": true, "requires": { - "ethers": "4.0.0-beta.3", + "@ethersproject/abi": "5.0.7", "underscore": "1.9.1", - "web3-utils": "1.2.2" + "web3-utils": "1.3.5" }, "dependencies": { - "@types/node": { - "version": "10.17.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.55.tgz", - "integrity": "sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==", - "dev": true - }, - "elliptic": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", - "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "@ethersproject/abi": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz", + "integrity": "sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==", "dev": true, "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/strings": "^5.0.4" } }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - }, - "dependencies": { - "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - } - } - }, - "ethers": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", - "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", - "dev": true, - "requires": { - "@types/node": "^10.3.2", - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "elliptic": "6.3.3", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.3", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, - "scrypt-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", - "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", - "dev": true - }, - "setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", - "dev": true - }, - "uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", - "dev": true - }, "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", + "integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==", "dev": true, "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", "ethereum-bloom-filters": "^1.0.6", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", "randombytes": "^2.1.0", "underscore": "1.9.1", "utf8": "3.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - } } } } }, "web3-eth-accounts": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.2.tgz", - "integrity": "sha512-KzHOEyXOEZ13ZOkWN3skZKqSo5f4Z1ogPFNn9uZbKCz+kSp+gCAEKxyfbOsB/JMAp5h7o7pb6eYsPCUBJmFFiA==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.3.5.tgz", + "integrity": "sha512-r3WOR21rgm6Cd6OFnifr3Tizdm5K+g2TsSOPySwX4FrgLrYDL6ck4zr5VXUPz+llpSExb/JztpE8pqEHr3U2NA==", "dev": true, "requires": { - "any-promise": "1.3.0", "crypto-browserify": "3.12.0", - "eth-lib": "0.2.7", + "eth-lib": "0.2.8", "ethereumjs-common": "^1.3.2", "ethereumjs-tx": "^2.1.1", - "scrypt-shim": "github:web3-js/scrypt-shim", + "scrypt-js": "^3.0.1", "underscore": "1.9.1", "uuid": "3.3.2", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-utils": "1.2.2" + "web3-core": "1.3.5", + "web3-core-helpers": "1.3.5", + "web3-core-method": "1.3.5", + "web3-utils": "1.3.5" }, "dependencies": { - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", @@ -21582,73 +20693,48 @@ "dev": true }, "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", + "integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==", "dev": true, "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", "ethereum-bloom-filters": "^1.0.6", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", "randombytes": "^2.1.0", "underscore": "1.9.1", "utf8": "3.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - } } } } }, "web3-eth-contract": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.2.tgz", - "integrity": "sha512-EKT2yVFws3FEdotDQoNsXTYL798+ogJqR2//CaGwx3p0/RvQIgfzEwp8nbgA6dMxCsn9KOQi7OtklzpnJMkjtA==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.3.5.tgz", + "integrity": "sha512-WfGVeQquN3D7Qm+KEIN9EI7yrm/fL2V9Y4+YhDWiKA/ns1pX1LYcEWojTOnBXCnPF3tcvoKKL+KBxXg1iKm38A==", "dev": true, "requires": { - "@types/bn.js": "^4.11.4", + "@types/bn.js": "^4.11.5", "underscore": "1.9.1", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-core-promievent": "1.2.2", - "web3-core-subscriptions": "1.2.2", - "web3-eth-abi": "1.2.2", - "web3-utils": "1.2.2" + "web3-core": "1.3.5", + "web3-core-helpers": "1.3.5", + "web3-core-method": "1.3.5", + "web3-core-promievent": "1.3.5", + "web3-core-subscriptions": "1.3.5", + "web3-eth-abi": "1.3.5", + "web3-utils": "1.3.5" }, "dependencies": { - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", + "integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==", "dev": true, "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", "ethereum-bloom-filters": "^1.0.6", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", @@ -21660,46 +20746,30 @@ } }, "web3-eth-ens": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.2.tgz", - "integrity": "sha512-CFjkr2HnuyMoMFBoNUWojyguD4Ef+NkyovcnUc/iAb9GP4LHohKrODG4pl76R5u61TkJGobC2ij6TyibtsyVYg==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.3.5.tgz", + "integrity": "sha512-5bkpFTXV18CvaVP8kCbLZZm2r1TWUv9AsXH+80yz8bTZulUGvXsBMRfK6e5nfEr2Yv59xlIXCFoalmmySI9EJw==", "dev": true, "requires": { + "content-hash": "^2.5.2", "eth-ens-namehash": "2.0.8", "underscore": "1.9.1", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-promievent": "1.2.2", - "web3-eth-abi": "1.2.2", - "web3-eth-contract": "1.2.2", - "web3-utils": "1.2.2" + "web3-core": "1.3.5", + "web3-core-helpers": "1.3.5", + "web3-core-promievent": "1.3.5", + "web3-eth-abi": "1.3.5", + "web3-eth-contract": "1.3.5", + "web3-utils": "1.3.5" }, "dependencies": { - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", + "integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==", "dev": true, "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", "ethereum-bloom-filters": "^1.0.6", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", @@ -21711,40 +20781,23 @@ } }, "web3-eth-iban": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.2.tgz", - "integrity": "sha512-gxKXBoUhaTFHr0vJB/5sd4i8ejF/7gIsbM/VvemHT3tF5smnmY6hcwSMmn7sl5Gs+83XVb/BngnnGkf+I/rsrQ==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.3.5.tgz", + "integrity": "sha512-x+BI/d2Vt0J1cKK8eFd4W0f1TDjgEOYCwiViTb28lLE+tqrgyPqWDA+l6UlKYLF/yMFX3Dym4ofcCOtgcn4q4g==", "dev": true, "requires": { - "bn.js": "4.11.8", - "web3-utils": "1.2.2" + "bn.js": "^4.11.9", + "web3-utils": "1.3.5" }, "dependencies": { - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", + "integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==", "dev": true, "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", "ethereum-bloom-filters": "^1.0.6", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", @@ -21756,50 +20809,33 @@ } }, "web3-eth-personal": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.2.tgz", - "integrity": "sha512-4w+GLvTlFqW3+q4xDUXvCEMU7kRZ+xm/iJC8gm1Li1nXxwwFbs+Y+KBK6ZYtoN1qqAnHR+plYpIoVo27ixI5Rg==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.3.5.tgz", + "integrity": "sha512-xELQHNZ8p3VoO1582ghCaq+Bx7pSkOOalc6/ACOCGtHDMelqgVejrmSIZGScYl+k0HzngmQAzURZWQocaoGM1g==", "dev": true, "requires": { - "@types/node": "^12.6.1", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-net": "1.2.2", - "web3-utils": "1.2.2" + "@types/node": "^12.12.6", + "web3-core": "1.3.5", + "web3-core-helpers": "1.3.5", + "web3-core-method": "1.3.5", + "web3-net": "1.3.5", + "web3-utils": "1.3.5" }, "dependencies": { "@types/node": { - "version": "12.20.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.6.tgz", - "integrity": "sha512-sRVq8d+ApGslmkE9e3i+D3gFGk7aZHAT+G4cIpIEdLJYPsWiSPwcAnJEjddLQQDqV3Ra2jOclX/Sv6YrvGYiWA==", + "version": "12.20.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.10.tgz", + "integrity": "sha512-TxCmnSSppKBBOzYzPR2BR25YlX5Oay8z2XGwFBInuA/Co0V9xJhLlW4kjbxKtgeNo3NOMbQP1A5Rc03y+XecPw==", "dev": true }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", + "integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==", "dev": true, "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", "ethereum-bloom-filters": "^1.0.6", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", @@ -21811,41 +20847,24 @@ } }, "web3-net": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.2.tgz", - "integrity": "sha512-K07j2DXq0x4UOJgae65rWZKraOznhk8v5EGSTdFqASTx7vWE/m+NqBijBYGEsQY1lSMlVaAY9UEQlcXK5HzXTw==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.3.5.tgz", + "integrity": "sha512-usbFbuUpKK8s7jPLGoUzi/WpNnefGFPTj948aJv8BZ04UQA4L/XS5NNkkhk358zNMmhGfEFW8wrWy+0Oy0njtA==", "dev": true, "requires": { - "web3-core": "1.2.2", - "web3-core-method": "1.2.2", - "web3-utils": "1.2.2" + "web3-core": "1.3.5", + "web3-core-method": "1.3.5", + "web3-utils": "1.3.5" }, "dependencies": { - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", + "integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==", "dev": true, "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", "ethereum-bloom-filters": "^1.0.6", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", @@ -21857,47 +20876,48 @@ } }, "web3-providers-http": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.2.tgz", - "integrity": "sha512-BNZ7Hguy3eBszsarH5gqr9SIZNvqk9eKwqwmGH1LQS1FL3NdoOn7tgPPdddrXec4fL94CwgNk4rCU+OjjZRNDg==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.3.5.tgz", + "integrity": "sha512-ZQOmceFjcajEZdiuqciXjijwIYWNmEJ1oxMtbrwB2eGxHRCMXEH2xGRUZuhOFNF88yQC/VXVi14yvYg5ZlFJlA==", "dev": true, "requires": { - "web3-core-helpers": "1.2.2", + "web3-core-helpers": "1.3.5", "xhr2-cookies": "1.1.0" } }, "web3-providers-ipc": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.2.tgz", - "integrity": "sha512-t97w3zi5Kn/LEWGA6D9qxoO0LBOG+lK2FjlEdCwDQatffB/+vYrzZ/CLYVQSoyFZAlsDoBasVoYSWZK1n39aHA==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.3.5.tgz", + "integrity": "sha512-cbZOeb/sALiHjzMolJjIyHla/J5wdL2JKUtRO66Nh/uLALBCpU8JUgzNvpAdJ1ae3+A33+EdFStdzuDYHKtQew==", "dev": true, "requires": { - "oboe": "2.1.4", + "oboe": "2.1.5", "underscore": "1.9.1", - "web3-core-helpers": "1.2.2" + "web3-core-helpers": "1.3.5" } }, "web3-providers-ws": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.2.tgz", - "integrity": "sha512-Wb1mrWTGMTXOpJkL0yGvL/WYLt8fUIXx8k/l52QB2IiKzvyd42dTWn4+j8IKXGSYYzOm7NMqv6nhA5VDk12VfA==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.3.5.tgz", + "integrity": "sha512-zeZ4LMvKhYaJBDCqA//Bzgp4r/T0tNq5U/xvN0axA4YflzF7yqlsbzGwCkcZYDbrUaK3Ltl2uOmvwjbWALOZ1A==", "dev": true, "requires": { + "eventemitter3": "4.0.4", "underscore": "1.9.1", - "web3-core-helpers": "1.2.2", - "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" + "web3-core-helpers": "1.3.5", + "websocket": "^1.0.32" } }, "web3-shh": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.2.tgz", - "integrity": "sha512-og258NPhlBn8yYrDWjoWBBb6zo1OlBgoWGT+LL5/LPqRbjPe09hlOYHgscAAr9zZGtohTOty7RrxYw6Z6oDWCg==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.3.5.tgz", + "integrity": "sha512-aRwzCduXvuGVslLL/Y15VcOHa70Qr2kxZI7UwOzQVhaaOdxuRRvo3AK/cmyln1Tsd54/n93Yk8I3qg5I2+6alw==", "dev": true, "requires": { - "web3-core": "1.2.2", - "web3-core-method": "1.2.2", - "web3-core-subscriptions": "1.2.2", - "web3-net": "1.2.2" + "web3-core": "1.3.5", + "web3-core-method": "1.3.5", + "web3-core-subscriptions": "1.3.5", + "web3-net": "1.3.5" } }, "web3-utils": { @@ -21917,14 +20937,16 @@ } }, "websocket": { - "version": "github:web3-js/WebSocket-Node#ef5ea2f41daf4a2113b80c9223df884b4d56c400", - "from": "github:web3-js/WebSocket-Node#polyfill/globalThis", + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", + "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", "dev": true, "requires": { + "bufferutil": "^4.0.1", "debug": "^2.2.0", "es5-ext": "^0.10.50", - "nan": "^2.14.0", "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", "yaeti": "^0.0.6" }, "dependencies": { @@ -21979,6 +21001,21 @@ "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", "dev": true }, + "which-typed-array": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz", + "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.0", + "es-abstract": "^1.18.0-next.1", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + } + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", diff --git a/package.json b/package.json index 91f13f6d..dbeb8ce1 100644 --- a/package.json +++ b/package.json @@ -118,7 +118,7 @@ "prettier": "^2.0.5", "prettier-plugin-solidity": "^1.0.0-alpha.53", "pretty-quick": "^2.0.1", - "solidity-coverage": "0.7.10", + "solidity-coverage": "^0.7.16", "temp-hardhat-etherscan": "^2.0.2", "ts-generator": "^0.1.1", "ts-node": "^8.10.2", From 7f881209d8fb81b6afedc1bdeabcf65455e3e0dd Mon Sep 17 00:00:00 2001 From: The-3D <37953689+The-3D@users.noreply.github.com> Date: Fri, 23 Apr 2021 18:36:10 +0200 Subject: [PATCH 209/219] Added license badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2ccc518d..1609baf9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0) ``` .///. .///. //. .// `/////////////- `++:++` .++:++` :++` `++: `++:......---.` From 50b1a5ff37dd669163a121b29ee068d1b9680307 Mon Sep 17 00:00:00 2001 From: David Racero Date: Fri, 23 Apr 2021 23:31:59 +0200 Subject: [PATCH 210/219] Added "build" badge from Github Actions --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1609baf9..658c7a91 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0) +![Build pass](https://github.com/AAVE/protocol-v2/actions/workflows/node.js.yml/badge.svg) ``` .///. .///. //. .// `/////////////- `++:++` .++:++` :++` `++: `++:......---.` From ba51b6a048e3d26eb068bd7eebf8fd77908a0f35 Mon Sep 17 00:00:00 2001 From: David Racero Date: Fri, 23 Apr 2021 23:34:55 +0200 Subject: [PATCH 211/219] rename: Workflow name set to "Build" for better badge naming --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 094c2263..7e24fc10 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -1,4 +1,4 @@ -name: Aave Actions +name: Build on: push: From aeae16b22f5b83278aff3b623fde1df97b6a5d9c Mon Sep 17 00:00:00 2001 From: David Racero Date: Fri, 23 Apr 2021 23:44:09 +0200 Subject: [PATCH 212/219] readme: link Build badge to Github Actions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 658c7a91..d59473e7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0) -![Build pass](https://github.com/AAVE/protocol-v2/actions/workflows/node.js.yml/badge.svg) +[![Build pass](https://github.com/AAVE/protocol-v2/actions/workflows/node.js.yml/badge.svg)](https://github.com/aave/protocol-v2/actions/workflows/node.js.yml) ``` .///. .///. //. .// `/////////////- `++:++` .++:++` :++` `++: `++:......---.` From 60dc2346c822e7faa6d7a31cb38b3d5d22c30cdc Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 26 Apr 2021 12:26:30 +0200 Subject: [PATCH 213/219] fix: added try catch for incentives controller interactions --- contracts/misc/UiPoolDataProvider.sol | 78 ++++++++++++++++++--------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index a3f25c05..6a051f23 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -131,38 +131,61 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ); // incentives - ( - reserveData.aEmissionPerSecond, - reserveData.aIncentivesLastUpdateTimestamp, - reserveData.aTokenIncentivesIndex - ) = incentivesController.getAssetData(reserveData.aTokenAddress); + try incentivesController.getAssetData(reserveData.aTokenAddress) returns ( + uint256 aEmissionPerSecond, uint256 aIncentivesLastUpdateTimestamp, uint256 aTokenIncentivesIndex) { + + reserveData.aEmissionPerSecond = aEmissionPerSecond; + reserveData.aIncentivesLastUpdateTimestamp = aIncentivesLastUpdateTimestamp; + reserveData.aTokenIncentivesIndex = aTokenIncentivesIndex; + } catch Error(string memory /*reason*/) { + } + + try incentivesController.getAssetData(reserveData.variableDebtTokenAddress) returns ( + uint256 vEmissionPerSecond, uint256 vIncentivesLastUpdateTimestamp, uint256 vTokenIncentivesIndex) { + + reserveData.vEmissionPerSecond = vEmissionPerSecond; + reserveData.vIncentivesLastUpdateTimestamp = vIncentivesLastUpdateTimestamp; + reserveData.vTokenIncentivesIndex = vTokenIncentivesIndex; + } catch Error(string memory /*reason*/) { + } - ( - reserveData.sEmissionPerSecond, - reserveData.sIncentivesLastUpdateTimestamp, - reserveData.sTokenIncentivesIndex - ) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress); - - ( - reserveData.vEmissionPerSecond, - reserveData.vIncentivesLastUpdateTimestamp, - reserveData.vTokenIncentivesIndex - ) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress); + try incentivesController.getAssetData(reserveData.stableDebtTokenAddress) returns ( + uint256 sEmissionPerSecond, uint256 sIncentivesLastUpdateTimestamp, uint256 sTokenIncentivesIndex) { + + reserveData.sEmissionPerSecond = sEmissionPerSecond; + reserveData.sIncentivesLastUpdateTimestamp = sIncentivesLastUpdateTimestamp; + reserveData.sTokenIncentivesIndex = sTokenIncentivesIndex; + } catch Error(string memory /*reason*/) { + } if (user != address(0)) { // incentives - userReservesData[i].aTokenincentivesUserIndex = incentivesController.getUserAssetData( + try incentivesController.getUserAssetData( user, reserveData.aTokenAddress - ); - userReservesData[i].sTokenincentivesUserIndex = incentivesController.getUserAssetData( - user, - reserveData.stableDebtTokenAddress - ); - userReservesData[i].vTokenincentivesUserIndex = incentivesController.getUserAssetData( + ) returns ( + uint256 aTokenincentivesUserIndex) { + userReservesData[i].aTokenincentivesUserIndex = aTokenincentivesUserIndex; + } catch Error(string memory /*reason*/) { + } + + try incentivesController.getUserAssetData( user, reserveData.variableDebtTokenAddress - ); + ) returns ( + uint256 vTokenincentivesUserIndex) { + userReservesData[i].vTokenincentivesUserIndex = vTokenincentivesUserIndex; + } catch Error(string memory /*reason*/) { + } + + try incentivesController.getUserAssetData( + user, + reserveData.stableDebtTokenAddress + ) returns ( + uint256 sTokenincentivesUserIndex) { + userReservesData[i].sTokenincentivesUserIndex = sTokenincentivesUserIndex; + } catch Error(string memory /*reason*/) { + } // user reserve data userReservesData[i].underlyingAsset = reserveData.underlyingAsset; userReservesData[i].scaledATokenBalance = IAToken(reserveData.aTokenAddress) @@ -196,11 +219,16 @@ contract UiPoolDataProvider is IUiPoolDataProvider { } } + uint256 unclaimedRewards; + try incentivesController.getUserUnclaimedRewards(user) returns (uint256 rewards) { + unclaimedRewards = rewards; + } catch Error (string memory) {} + return ( reservesData, userReservesData, oracle.getAssetPrice(MOCK_USD_ADDRESS), - incentivesController.getUserUnclaimedRewards(user) + unclaimedRewards ); } } From 60ee0c54eb8e880b1392cc9f69f4381015b2b20b Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 26 Apr 2021 12:39:37 +0200 Subject: [PATCH 214/219] fix: added check if incentives contract is 0 --- contracts/misc/UiPoolDataProvider.sol | 85 +++++++++++---------------- 1 file changed, 33 insertions(+), 52 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 6a051f23..c24e8939 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -131,60 +131,41 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ); // incentives - try incentivesController.getAssetData(reserveData.aTokenAddress) returns ( - uint256 aEmissionPerSecond, uint256 aIncentivesLastUpdateTimestamp, uint256 aTokenIncentivesIndex) { - - reserveData.aEmissionPerSecond = aEmissionPerSecond; - reserveData.aIncentivesLastUpdateTimestamp = aIncentivesLastUpdateTimestamp; - reserveData.aTokenIncentivesIndex = aTokenIncentivesIndex; - } catch Error(string memory /*reason*/) { - } - - try incentivesController.getAssetData(reserveData.variableDebtTokenAddress) returns ( - uint256 vEmissionPerSecond, uint256 vIncentivesLastUpdateTimestamp, uint256 vTokenIncentivesIndex) { - - reserveData.vEmissionPerSecond = vEmissionPerSecond; - reserveData.vIncentivesLastUpdateTimestamp = vIncentivesLastUpdateTimestamp; - reserveData.vTokenIncentivesIndex = vTokenIncentivesIndex; - } catch Error(string memory /*reason*/) { - } + if (address(0) != address(incentivesController)) { + ( + reserveData.aEmissionPerSecond, + reserveData.aIncentivesLastUpdateTimestamp, + reserveData.aTokenIncentivesIndex + ) = incentivesController.getAssetData(reserveData.aTokenAddress); - try incentivesController.getAssetData(reserveData.stableDebtTokenAddress) returns ( - uint256 sEmissionPerSecond, uint256 sIncentivesLastUpdateTimestamp, uint256 sTokenIncentivesIndex) { - - reserveData.sEmissionPerSecond = sEmissionPerSecond; - reserveData.sIncentivesLastUpdateTimestamp = sIncentivesLastUpdateTimestamp; - reserveData.sTokenIncentivesIndex = sTokenIncentivesIndex; - } catch Error(string memory /*reason*/) { + ( + reserveData.sEmissionPerSecond, + reserveData.sIncentivesLastUpdateTimestamp, + reserveData.sTokenIncentivesIndex + ) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress); + + ( + reserveData.vEmissionPerSecond, + reserveData.vIncentivesLastUpdateTimestamp, + reserveData.vTokenIncentivesIndex + ) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress); } if (user != address(0)) { // incentives - try incentivesController.getUserAssetData( - user, - reserveData.aTokenAddress - ) returns ( - uint256 aTokenincentivesUserIndex) { - userReservesData[i].aTokenincentivesUserIndex = aTokenincentivesUserIndex; - } catch Error(string memory /*reason*/) { - } - - try incentivesController.getUserAssetData( - user, - reserveData.variableDebtTokenAddress - ) returns ( - uint256 vTokenincentivesUserIndex) { - userReservesData[i].vTokenincentivesUserIndex = vTokenincentivesUserIndex; - } catch Error(string memory /*reason*/) { - } - - try incentivesController.getUserAssetData( - user, - reserveData.stableDebtTokenAddress - ) returns ( - uint256 sTokenincentivesUserIndex) { - userReservesData[i].sTokenincentivesUserIndex = sTokenincentivesUserIndex; - } catch Error(string memory /*reason*/) { + if (address(0) != address(incentivesController)) { + userReservesData[i].aTokenincentivesUserIndex = incentivesController.getUserAssetData( + user, + reserveData.aTokenAddress + ); + userReservesData[i].sTokenincentivesUserIndex = incentivesController.getUserAssetData( + user, + reserveData.stableDebtTokenAddress + ); + userReservesData[i].vTokenincentivesUserIndex = incentivesController.getUserAssetData( + user, + reserveData.variableDebtTokenAddress + ); } // user reserve data userReservesData[i].underlyingAsset = reserveData.underlyingAsset; @@ -220,9 +201,9 @@ contract UiPoolDataProvider is IUiPoolDataProvider { } uint256 unclaimedRewards; - try incentivesController.getUserUnclaimedRewards(user) returns (uint256 rewards) { - unclaimedRewards = rewards; - } catch Error (string memory) {} + if (address(0) != address(incentivesController)) { + unclaimedRewards = incentivesController.getUserUnclaimedRewards(user); + } return ( reservesData, From 8b8736dc5a4956ae470990b3f4b05556b6cd5ab8 Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 26 Apr 2021 15:26:36 +0200 Subject: [PATCH 215/219] Back to try catch, but with also 0 address catching --- contracts/misc/UiPoolDataProvider.sol | 67 +++++++++++++++++---------- package-lock.json | 35 ++++++++------ 2 files changed, 64 insertions(+), 38 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index c24e8939..70aef7b9 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -132,40 +132,57 @@ contract UiPoolDataProvider is IUiPoolDataProvider { // incentives if (address(0) != address(incentivesController)) { - ( - reserveData.aEmissionPerSecond, - reserveData.aIncentivesLastUpdateTimestamp, - reserveData.aTokenIncentivesIndex - ) = incentivesController.getAssetData(reserveData.aTokenAddress); + try incentivesController.getAssetData(reserveData.aTokenAddress) returns ( + uint256 aEmissionPerSecond, uint256 aIncentivesLastUpdateTimestamp, uint256 aTokenIncentivesIndex) { - ( - reserveData.sEmissionPerSecond, - reserveData.sIncentivesLastUpdateTimestamp, - reserveData.sTokenIncentivesIndex - ) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress); + reserveData.aEmissionPerSecond = aEmissionPerSecond; + reserveData.aIncentivesLastUpdateTimestamp = aIncentivesLastUpdateTimestamp; + reserveData.aTokenIncentivesIndex = aTokenIncentivesIndex; + } catch Error(string memory /*reason*/) {} - ( - reserveData.vEmissionPerSecond, - reserveData.vIncentivesLastUpdateTimestamp, - reserveData.vTokenIncentivesIndex - ) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress); + try incentivesController.getAssetData(reserveData.variableDebtTokenAddress) returns ( + uint256 vEmissionPerSecond, uint256 vIncentivesLastUpdateTimestamp, uint256 vTokenIncentivesIndex) { + + reserveData.vEmissionPerSecond = vEmissionPerSecond; + reserveData.vIncentivesLastUpdateTimestamp = vIncentivesLastUpdateTimestamp; + reserveData.vTokenIncentivesIndex = vTokenIncentivesIndex; + } catch Error(string memory /*reason*/) {} + + try incentivesController.getAssetData(reserveData.stableDebtTokenAddress) returns ( + uint256 sEmissionPerSecond, uint256 sIncentivesLastUpdateTimestamp, uint256 sTokenIncentivesIndex) { + + reserveData.sEmissionPerSecond = sEmissionPerSecond; + reserveData.sIncentivesLastUpdateTimestamp = sIncentivesLastUpdateTimestamp; + reserveData.sTokenIncentivesIndex = sTokenIncentivesIndex; + } catch Error(string memory /*reason*/) {} } if (user != address(0)) { // incentives if (address(0) != address(incentivesController)) { - userReservesData[i].aTokenincentivesUserIndex = incentivesController.getUserAssetData( + try incentivesController.getUserAssetData( user, reserveData.aTokenAddress - ); - userReservesData[i].sTokenincentivesUserIndex = incentivesController.getUserAssetData( - user, - reserveData.stableDebtTokenAddress - ); - userReservesData[i].vTokenincentivesUserIndex = incentivesController.getUserAssetData( + ) returns ( + uint256 aTokenincentivesUserIndex) { + userReservesData[i].aTokenincentivesUserIndex = aTokenincentivesUserIndex; + } catch Error(string memory /*reason*/) {} + + try incentivesController.getUserAssetData( user, reserveData.variableDebtTokenAddress - ); + ) returns ( + uint256 vTokenincentivesUserIndex) { + userReservesData[i].vTokenincentivesUserIndex = vTokenincentivesUserIndex; + } catch Error(string memory /*reason*/) {} + + try incentivesController.getUserAssetData( + user, + reserveData.stableDebtTokenAddress + ) returns ( + uint256 sTokenincentivesUserIndex) { + userReservesData[i].sTokenincentivesUserIndex = sTokenincentivesUserIndex; + } catch Error(string memory /*reason*/) {} } // user reserve data userReservesData[i].underlyingAsset = reserveData.underlyingAsset; @@ -202,7 +219,9 @@ contract UiPoolDataProvider is IUiPoolDataProvider { uint256 unclaimedRewards; if (address(0) != address(incentivesController)) { - unclaimedRewards = incentivesController.getUserUnclaimedRewards(user); + // try incentivesController.getUserUnclaimedRewards(user) returns (uint256 rewards) { + // unclaimedRewards = rewards; + // } catch Error (string memory) {} } return ( diff --git a/package-lock.json b/package-lock.json index 6cd1ef03..c5cc43eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7709,6 +7709,15 @@ "requires": { "bn.js": "^5.0.0", "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true, + "optional": true + } } }, "browserify-sign": { @@ -7819,9 +7828,9 @@ }, "dependencies": { "node-gyp-build": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", - "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", "dev": true } } @@ -10891,14 +10900,6 @@ "requires": { "min-document": "^2.19.0", "process": "^0.11.10" - }, - "dependencies": { - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true - } } }, "got": { @@ -12575,6 +12576,12 @@ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -14241,9 +14248,9 @@ }, "dependencies": { "node-gyp-build": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", - "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", "dev": true } } From acc2207d81d136781735360f89bd513c33d6d245 Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 26 Apr 2021 15:57:26 +0200 Subject: [PATCH 216/219] added kovan config --- tasks/deployments/deploy-UiPoolDataProvider.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/deployments/deploy-UiPoolDataProvider.ts b/tasks/deployments/deploy-UiPoolDataProvider.ts index 984d5a13..6cc07449 100644 --- a/tasks/deployments/deploy-UiPoolDataProvider.ts +++ b/tasks/deployments/deploy-UiPoolDataProvider.ts @@ -11,10 +11,10 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider } const addressesByNetwork = { - // [eEthereumNetwork.kovan]: { - // incentivesController: '', - // aaveOracle: '', - // }, + [eEthereumNetwork.kovan]: { + incentivesController: '0x0000000000000000000000000000000000000000', + aaveOracle: '0x8fb777d67e9945e2c01936e319057f9d41d559e6', + }, [eEthereumNetwork.main]: { incentivesController: '0xd784927Ff2f95ba542BfC824c8a8a98F3495f6b5', aaveOracle: '0xa50ba011c48153de246e5192c8f9258a2ba79ca9', From f5f3adeb0f83f229ddf879346dbb5707bcb16e45 Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 26 Apr 2021 16:29:30 +0200 Subject: [PATCH 217/219] removed error from catch so it catches everything --- contracts/misc/UiPoolDataProvider.sol | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 70aef7b9..7a77c43a 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -138,7 +138,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { reserveData.aEmissionPerSecond = aEmissionPerSecond; reserveData.aIncentivesLastUpdateTimestamp = aIncentivesLastUpdateTimestamp; reserveData.aTokenIncentivesIndex = aTokenIncentivesIndex; - } catch Error(string memory /*reason*/) {} + } catch {} try incentivesController.getAssetData(reserveData.variableDebtTokenAddress) returns ( uint256 vEmissionPerSecond, uint256 vIncentivesLastUpdateTimestamp, uint256 vTokenIncentivesIndex) { @@ -146,7 +146,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { reserveData.vEmissionPerSecond = vEmissionPerSecond; reserveData.vIncentivesLastUpdateTimestamp = vIncentivesLastUpdateTimestamp; reserveData.vTokenIncentivesIndex = vTokenIncentivesIndex; - } catch Error(string memory /*reason*/) {} + } catch {} try incentivesController.getAssetData(reserveData.stableDebtTokenAddress) returns ( uint256 sEmissionPerSecond, uint256 sIncentivesLastUpdateTimestamp, uint256 sTokenIncentivesIndex) { @@ -154,7 +154,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { reserveData.sEmissionPerSecond = sEmissionPerSecond; reserveData.sIncentivesLastUpdateTimestamp = sIncentivesLastUpdateTimestamp; reserveData.sTokenIncentivesIndex = sTokenIncentivesIndex; - } catch Error(string memory /*reason*/) {} + } catch {} } if (user != address(0)) { @@ -166,7 +166,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ) returns ( uint256 aTokenincentivesUserIndex) { userReservesData[i].aTokenincentivesUserIndex = aTokenincentivesUserIndex; - } catch Error(string memory /*reason*/) {} + } catch {} try incentivesController.getUserAssetData( user, @@ -174,7 +174,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ) returns ( uint256 vTokenincentivesUserIndex) { userReservesData[i].vTokenincentivesUserIndex = vTokenincentivesUserIndex; - } catch Error(string memory /*reason*/) {} + } catch {} try incentivesController.getUserAssetData( user, @@ -182,7 +182,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ) returns ( uint256 sTokenincentivesUserIndex) { userReservesData[i].sTokenincentivesUserIndex = sTokenincentivesUserIndex; - } catch Error(string memory /*reason*/) {} + } catch {} } // user reserve data userReservesData[i].underlyingAsset = reserveData.underlyingAsset; @@ -219,9 +219,9 @@ contract UiPoolDataProvider is IUiPoolDataProvider { uint256 unclaimedRewards; if (address(0) != address(incentivesController)) { - // try incentivesController.getUserUnclaimedRewards(user) returns (uint256 rewards) { - // unclaimedRewards = rewards; - // } catch Error (string memory) {} + try incentivesController.getUserUnclaimedRewards(user) returns (uint256 rewards) { + unclaimedRewards = rewards; + } catch {} } return ( From d36b9fd14c0cf96dc927531d814713785f486f0a Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 26 Apr 2021 16:43:21 +0200 Subject: [PATCH 218/219] added other catch --- contracts/misc/UiPoolDataProvider.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 7a77c43a..bbb8290d 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -138,7 +138,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { reserveData.aEmissionPerSecond = aEmissionPerSecond; reserveData.aIncentivesLastUpdateTimestamp = aIncentivesLastUpdateTimestamp; reserveData.aTokenIncentivesIndex = aTokenIncentivesIndex; - } catch {} + } catch Error(string memory) {} catch (bytes memory) {} try incentivesController.getAssetData(reserveData.variableDebtTokenAddress) returns ( uint256 vEmissionPerSecond, uint256 vIncentivesLastUpdateTimestamp, uint256 vTokenIncentivesIndex) { @@ -146,7 +146,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { reserveData.vEmissionPerSecond = vEmissionPerSecond; reserveData.vIncentivesLastUpdateTimestamp = vIncentivesLastUpdateTimestamp; reserveData.vTokenIncentivesIndex = vTokenIncentivesIndex; - } catch {} + } catch Error(string memory) {} catch (bytes memory) {} try incentivesController.getAssetData(reserveData.stableDebtTokenAddress) returns ( uint256 sEmissionPerSecond, uint256 sIncentivesLastUpdateTimestamp, uint256 sTokenIncentivesIndex) { @@ -154,7 +154,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { reserveData.sEmissionPerSecond = sEmissionPerSecond; reserveData.sIncentivesLastUpdateTimestamp = sIncentivesLastUpdateTimestamp; reserveData.sTokenIncentivesIndex = sTokenIncentivesIndex; - } catch {} + } catch Error(string memory) {} catch (bytes memory) {} } if (user != address(0)) { @@ -166,7 +166,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ) returns ( uint256 aTokenincentivesUserIndex) { userReservesData[i].aTokenincentivesUserIndex = aTokenincentivesUserIndex; - } catch {} + } catch Error(string memory) {} catch (bytes memory) {} try incentivesController.getUserAssetData( user, @@ -174,7 +174,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ) returns ( uint256 vTokenincentivesUserIndex) { userReservesData[i].vTokenincentivesUserIndex = vTokenincentivesUserIndex; - } catch {} + } catch Error(string memory) {} catch (bytes memory) {} try incentivesController.getUserAssetData( user, @@ -182,7 +182,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ) returns ( uint256 sTokenincentivesUserIndex) { userReservesData[i].sTokenincentivesUserIndex = sTokenincentivesUserIndex; - } catch {} + } catch Error(string memory) {} catch (bytes memory) {} } // user reserve data userReservesData[i].underlyingAsset = reserveData.underlyingAsset; From c1c2cffd2671678c02381c862233429d76145cf1 Mon Sep 17 00:00:00 2001 From: sendra Date: Mon, 26 Apr 2021 17:51:39 +0200 Subject: [PATCH 219/219] remove try catch as it doesnt catch the implementation exeption --- contracts/misc/UiPoolDataProvider.sol | 68 +++++++++------------------ 1 file changed, 22 insertions(+), 46 deletions(-) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index bbb8290d..63dd7a1c 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -132,57 +132,40 @@ contract UiPoolDataProvider is IUiPoolDataProvider { // incentives if (address(0) != address(incentivesController)) { - try incentivesController.getAssetData(reserveData.aTokenAddress) returns ( - uint256 aEmissionPerSecond, uint256 aIncentivesLastUpdateTimestamp, uint256 aTokenIncentivesIndex) { + ( + reserveData.aEmissionPerSecond, + reserveData.aIncentivesLastUpdateTimestamp, + reserveData.aTokenIncentivesIndex + ) = incentivesController.getAssetData(reserveData.aTokenAddress); - reserveData.aEmissionPerSecond = aEmissionPerSecond; - reserveData.aIncentivesLastUpdateTimestamp = aIncentivesLastUpdateTimestamp; - reserveData.aTokenIncentivesIndex = aTokenIncentivesIndex; - } catch Error(string memory) {} catch (bytes memory) {} + ( + reserveData.sEmissionPerSecond, + reserveData.sIncentivesLastUpdateTimestamp, + reserveData.sTokenIncentivesIndex + ) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress); - try incentivesController.getAssetData(reserveData.variableDebtTokenAddress) returns ( - uint256 vEmissionPerSecond, uint256 vIncentivesLastUpdateTimestamp, uint256 vTokenIncentivesIndex) { - - reserveData.vEmissionPerSecond = vEmissionPerSecond; - reserveData.vIncentivesLastUpdateTimestamp = vIncentivesLastUpdateTimestamp; - reserveData.vTokenIncentivesIndex = vTokenIncentivesIndex; - } catch Error(string memory) {} catch (bytes memory) {} - - try incentivesController.getAssetData(reserveData.stableDebtTokenAddress) returns ( - uint256 sEmissionPerSecond, uint256 sIncentivesLastUpdateTimestamp, uint256 sTokenIncentivesIndex) { - - reserveData.sEmissionPerSecond = sEmissionPerSecond; - reserveData.sIncentivesLastUpdateTimestamp = sIncentivesLastUpdateTimestamp; - reserveData.sTokenIncentivesIndex = sTokenIncentivesIndex; - } catch Error(string memory) {} catch (bytes memory) {} + ( + reserveData.vEmissionPerSecond, + reserveData.vIncentivesLastUpdateTimestamp, + reserveData.vTokenIncentivesIndex + ) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress); } if (user != address(0)) { // incentives if (address(0) != address(incentivesController)) { - try incentivesController.getUserAssetData( + userReservesData[i].aTokenincentivesUserIndex = incentivesController.getUserAssetData( user, reserveData.aTokenAddress - ) returns ( - uint256 aTokenincentivesUserIndex) { - userReservesData[i].aTokenincentivesUserIndex = aTokenincentivesUserIndex; - } catch Error(string memory) {} catch (bytes memory) {} - - try incentivesController.getUserAssetData( + ); + userReservesData[i].vTokenincentivesUserIndex = incentivesController.getUserAssetData( user, reserveData.variableDebtTokenAddress - ) returns ( - uint256 vTokenincentivesUserIndex) { - userReservesData[i].vTokenincentivesUserIndex = vTokenincentivesUserIndex; - } catch Error(string memory) {} catch (bytes memory) {} - - try incentivesController.getUserAssetData( + ); + userReservesData[i].sTokenincentivesUserIndex = incentivesController.getUserAssetData( user, reserveData.stableDebtTokenAddress - ) returns ( - uint256 sTokenincentivesUserIndex) { - userReservesData[i].sTokenincentivesUserIndex = sTokenincentivesUserIndex; - } catch Error(string memory) {} catch (bytes memory) {} + ); } // user reserve data userReservesData[i].underlyingAsset = reserveData.underlyingAsset; @@ -217,18 +200,11 @@ contract UiPoolDataProvider is IUiPoolDataProvider { } } - uint256 unclaimedRewards; - if (address(0) != address(incentivesController)) { - try incentivesController.getUserUnclaimedRewards(user) returns (uint256 rewards) { - unclaimedRewards = rewards; - } catch {} - } - return ( reservesData, userReservesData, oracle.getAssetPrice(MOCK_USD_ADDRESS), - unclaimedRewards + incentivesController.getUserUnclaimedRewards(user) ); } }